Greasy Fork is available in English.

跟踪链接净化

净化所有网站上的跟踪链接和事件

  1. // ==UserScript==
  2. // @name 跟踪链接净化
  3. // @name:zh-CN 跟踪链接净化
  4. // @name:zh-TW 跟蹤鏈接凈化
  5. // @name:en Clean Tracking URLs
  6. // @name:ja トラッカーの浄化
  7. // @name:ko 추적 URL 정리
  8. // @name:ru Очистить ссылки отслеживания
  9. // @name:de Tracking-URLs bereinigen
  10. // @name:fr Nettoyer les URLs de suivi
  11. // @name:es Limpiar URLs de seguimiento
  12. // @namespace https://github.com/cilxe/JavaScriptProjects
  13. // @author cilxe
  14. // @version 0.7.8
  15. // @description 净化所有网站上的跟踪链接和事件
  16. // @description:zh-CN 净化所有网站上的跟踪链接和事件
  17. // @description:zh-TW 凈化網際網路上的所有網站鏈接和事件
  18. // @description:en Clean all tracking URLs, block tracking events on all websites
  19. // @description:ja すべてのサイトの追跡リンクとイベントをサニタイズする
  20. // @description:ko 모든 추적 URL 정리, 모든 웹사이트에서 추적 이벤트 차단
  21. // @description:ru Очистить все ссылки отслеживания, заблокировать события отслеживания на всех веб-сайтах
  22. // @description:de Alle Tracking-URLs bereinigen, Tracking-Ereignisse auf allen Websites blockieren
  23. // @description:fr Nettoyer toutes les URLs de suivi, bloquer les événements de suivi sur tous les sites
  24. // @description:es Limpiar todas las URLs de seguimiento, bloquear eventos de seguimiento en todos los sitios web
  25. // @match *://*/*
  26. // @exclude /^https?:\/\/([a-z0-9-.]{0,52})(hdslb.com|csdnimg.cn)\/.*$/
  27. // @run-at document-start
  28. // @grant GM_registerMenuCommand
  29. // @grant GM_getValue
  30. // @grant GM_setValue
  31. // @icon data:image/png;base64,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
  32. // @license MIT
  33. // ==/UserScript==
  34. /*
  35. ## Main features
  36. - Auto clean up all URLs and block tracking events by default.
  37. - Manually clean all links with keyboard shortcuts (Shift + Alt + X). `(v0.6.3~)`
  38.  
  39. ## Additional features (via the script menu)
  40. - Manually clean up the links again. `(v0.5.2~)`
  41. - Add specific tracking params for the current site (match by domain). `(v0.6.1~)`
  42. - Remove custom added params for the current site (match by domain). `(v0.6.2~)`
  43.  
  44. ## Websites that support common cleaning
  45. - All websites on the internet.
  46.  
  47. ## Websites that support additional cleaning
  48. - Bilibili
  49. - Baidu (Unencrypted) URLs
  50. - CSDN
  51. - Alibaba sites
  52. - alibaba.com/aliyun.com/alibabagroup.com/alimama.com
  53. - taobao.com/tmall.com/tmall.hk/1688.com/aliexpress.com/trendyol/lazada
  54. - youku.com
  55. - Douyin/Tiktok.com
  56. - Amazon
  57. - Youtube
  58. */
  59. (() => {
  60. const DELAY_TIME = { fast: 600, normal: 1000, slow: 3000 };
  61. const doc = document;
  62. const pageHost = window.location.hostname;
  63. const pageURL = window.location.href;
  64. const pagePath = window.location.pathname;
  65. let topScroll = 0;
  66. let isLogin = false;
  67. const hostRegex = /[a-z0-9-]{1,128}\.[a-z]{2,15}$/;
  68. // Matches all tracking parameters *contains/starts/ends* with the name
  69. const paramsRegStr = '^(spm|from_|ref_|track|trk|share_|embeds_|refer_)|'
  70. + '_from$|scm|referrer';
  71. let paramsReg = new RegExp(paramsRegStr);
  72.  
  73. const commonParams = ['spm', 'mkt', 'src', 'from', 'source', 'alias',
  74. 'vd_source', 'brand', 'curator_clanid', 'snr', 'redir', 'sprefix',
  75. 'utm_id', 'utm_content', 'utm_source', 'utm_medium', 'utm_sources',
  76. 'utm_term', 'utm_campaign', 'utm_referrer', 'utm_keyword', 'ref',
  77. 'feature'];
  78.  
  79. // Tracking or other params for certain sites
  80. const bilibiliParams = ['vd_source', 'hotRank', 'launch_id', 'popular_rank',
  81. 'session_id', 'business', 'sort_field', 'is_room_feed', 'visit_id',
  82. 'is_live_full_webview', 'is_live_webview', 'vt', 'theme', 'noReffer',
  83. 'timestamp', 'unique_k', 'hasBack', 'noTitleBar', 'plat_id', 'is_preview',
  84. 'buvid', 'up_id', 'is_story_h5', 'hybrid_set_header', 'lottery_id', 'seid',
  85. '-Abrowser', 'from', 'pagefrom', 'schema', 'preUrl', 'jumpLinkType',
  86. 'referfrom', 'spm_id', 'plat_id', 'p2p_type', 'broadcast_type',
  87. 'event_source_type'];
  88. // 'share_medium', 'share_plat', 'share_source', 'share_tag'
  89. // 'from_source', 'from_spmid', 'goFrom', 'sourceFrom', 'share_session_id'
  90. // 'refer_from', 'spm_id_from', 'dynamicspm_id_from', 'extra_jump_from'
  91. // 'search_source', 'bsource', 'msource', 'csource'
  92. // 'p2p_type', 'broadcast_type', 'event_source_type'
  93. const biliParamsReg = /^(utm_|share_|spm|from_)|(From|_from|source)$/;
  94.  
  95. const baiduParams = ['rsv_idx', 'hisfilter', 'rsf', 'rsv_pq', 'rsv_t', 'qid', // baidu
  96. 'rsv_dl', 'oq', 'gpc', 'usm', 'tfflag', 'bs', 'rqlang', 'tn',
  97. 'sc_us', 'wfr', 'fenlei', 'platform', 'rqid', 'base_query', 'entry', 'qbl',
  98. 'for', 'from', 'topic_pn', 'rsp', 'rs_src', 'f', 'rsv_page', 'dyTabStr',
  99. 'ct', 'lm', 'site', 'sites', 'fr', 'cl', 'bsst', 'lid', 'rsv_spt',
  100. 'rsv_bp', 'src', 'sfrom', 'refer', 'zp_fr', 'channel', 'p_from', 'n_type',
  101. 'eqid', '_at_', 'sa', 'pd', 'source', 'tag_key', 'uname', 'uid',
  102. 'fromModule', 'lemmaFrom', 'structureId', 'structureClickId', 'ie',
  103. 'structureItemId', 'xzhid', 'rsv_enter', 'rsv_btype', 'prefixsug',
  104. 'client_type', 'task', 'locate', 'page', 'type', 'is_new_user', 'frwh', // tieba
  105. 'obj_id', 'fid', 'fname', '_t', 'topic_name', 'frs', 'share_from', 'tpl',
  106. 'u', 'tb_mod', 'tb_fr', 'share', 'sfc', 'idfrom', 'client_version', 'st',
  107. 'qq-pf-to',
  108. 'unique', 'is_video', '_wkts_', 'ai', 'ck', 'shh', // wenku
  109. 'utm_source', 'utm_medium', 'utm_term', 'utm_campaign', 'utm_content',
  110. 'utm_id',
  111. ];
  112.  
  113. const douyinParams = ['rsv_idx', 'hisfilter', 'source', 'aid', 'enter_from',
  114. 'focus_method', 'previous_page', 'extra_params', 'gid', 'enter_method', // douyin
  115. 'is_from_webapp', 'sender_device', 'web_id']; // tiktok
  116.  
  117. // 'from_wecom', 'source',
  118. const csdnParams = commonParams.concat(['ops_request_misc', 'request_id',
  119. 'biz_id', 'ydreferer', 'usp']);
  120.  
  121. const youkuTudouParams = ['spm', 'scm', 'from', 's', 'playMode', 'client_id'];
  122.  
  123. const aliSitesStr = '(alibaba|alibabagroup|aliyun|alimama|aliexpress'
  124. + '|taobao|tmall|1688|jiyoujia|fliggy)'
  125. + '.(com|hk|cn)$|(lazada|trendyol).[a-z.]{2,15}$';
  126. const aliSitesReg = new RegExp(aliSitesStr);
  127.  
  128. const aliParams = [
  129. 'spm', 'acm', 'scm', 'scene', 'from', 'pvid', 'pvid2',
  130. ]; // 'wh_pid', 'wh_random_str', 'wx_navbar_transparent', 'wh_weex'
  131. const aliParamsRegStr = '^(utm_|spm_|from_|ref|track|wh_|wx_)';
  132. const aliParamsReg = new RegExp(aliParamsRegStr);
  133.  
  134. const amaznParams = ['content-id', 'qid', 'crid', 'isAmazonFulfilled',
  135. 'sbo', 'plattr', 'sprefix', 'ld', '_encoding', 'ie', 'ds',
  136. ];
  137. const amznParamsRegStr = '_ref|^(utm_|ref|pd_rd_|pf_rd_|track|sc_)';
  138. const amznParamsReg = new RegExp(amznParamsRegStr, 'i');
  139.  
  140. const ytParams = commonParams.concat(['embeds_referring_euri', 'embeds_euri',
  141. 'source_ve_path', 'feature', 'embeds_referring_origin', 'redir_token',
  142. 'pp', 'origin', 'ab_channel', 'enablejsapi', 'widgetid']);
  143.  
  144. // If <true> block [Lucky Draw (The Selection)] popups on live.bilibili.com.
  145. const BlockLivePopups = true;
  146.  
  147. // Add a custom 'urlchange' event to pushState and replaceState
  148. (() => { // [https://stackoverflow.com/a/52809105]
  149. const originalPushState = window.history.pushState;
  150. const originalReplaceState = window.history.replaceState;
  151. window.history.pushState = function pushState(...args) {
  152. const newPushState = originalPushState.apply(this, args);
  153. window.dispatchEvent(new Event('pushstate'));
  154. window.dispatchEvent(new Event('urlchange'));
  155. return newPushState;
  156. };
  157. window.history.replaceState = function replaceState(...args) {
  158. const newReplaceState = originalReplaceState.apply(this, args);
  159. window.dispatchEvent(new Event('replacestate'));
  160. window.dispatchEvent(new Event('urlchange'));
  161. return newReplaceState;
  162. };
  163. })();
  164. // Restore history state, remove redundant parameters
  165. function restoreState(siteParams) {
  166. const url = new URL(window.location.href);
  167. const params = url.searchParams;
  168. siteParams.forEach((k) => { if (params.has(k)) { params.delete(k); } });
  169. Array.from(params.keys()).forEach((k) => {
  170. if (paramsReg.test(k)) { params.delete(k); }
  171. });
  172. if (url.href !== window.location.href) {
  173. window.history.replaceState({}, 'Restore', url.href);
  174. }
  175. }
  176. let cleanLinks; // Clean most of <a> links
  177. switch (true) {
  178. case aliSitesReg.test(pageHost): // Alibaba sites
  179. cleanLinks = (siteParams) => {
  180. const links = doc.getElementsByTagName('a');
  181. for (let i = 0; i < links.length; i += 1) {
  182. if (hostRegex.test(links[i].hostname)) {
  183. const url = new URL(links[i].href);
  184. const params = url.searchParams;
  185. if (params.has('q')) { params.set('q', links[i].innerText); } // // 1. Ali sites (decoding error)
  186. siteParams.forEach((k) => { if (params.has(k)) { params.delete(k); } });
  187. Array.from(params.keys()).forEach((k) => { if (aliParamsReg.test(k)) { params.delete(k); } });
  188. if (links[i].href !== url.href) { links[i].href = url.href; }
  189. }
  190. }
  191. const areaLinks = doc.getElementsByTagName('area');
  192. for (let i = 0; i < areaLinks.length; i += 1) {
  193. if (hostRegex.test(areaLinks[i].hostname)) {
  194. const url = new URL(areaLinks[i].href);
  195. const params = url.searchParams;
  196. if (params.has('q')) { params.set('q', areaLinks[i].innerText); } // // 1. Ali sites (decoding error)
  197. siteParams.forEach((k) => { if (params.has(k)) { params.delete(k); } });
  198. Array.from(params.keys()).forEach((k) => { if (aliParamsReg.test(k)) { params.delete(k); } });
  199. if (areaLinks[i].href !== url.href) { areaLinks[i].href = url.href; }
  200. }
  201. }
  202. };
  203. break;
  204. case /baidu.com$/.test(pageHost): // Baidu sites
  205. cleanLinks = (siteParams) => {
  206. const links = doc.getElementsByTagName('a');
  207. for (let i = 0; i < links.length; i += 1) {
  208. if (hostRegex.test(links[i].hostname)) {
  209. const url = new URL(links[i].href);
  210. const params = url.searchParams;
  211. if (links[i].hostname === 'passport.baidu.com' && siteParams.includes('u')) {
  212. siteParams.splice(siteParams.indexOf('u'), 1);
  213. }
  214. if (links[i].innerText === '应用中心') { params.set('kw', links[i].innerText); } // 2. Tieba.baidu.com
  215. siteParams.forEach((k) => { if (params.has(k)) { params.delete(k); } });
  216. if (url.href !== links[i].href) { links[i].href = url.href; }
  217. }
  218. }
  219. };
  220. break;
  221. case /(bilibili|biligame)\.com$/.test(pageHost):
  222. cleanLinks = (siteParams) => {
  223. const links = doc.getElementsByTagName('a');
  224. for (let i = 0; i < links.length; i += 1) {
  225. if (hostRegex.test(links[i].hostname)) {
  226. links[i].removeAttribute('data-mod');
  227. links[i].removeAttribute('data-spmid');
  228. links[i].removeAttribute('data-idx');
  229. links[i].removeAttribute('data-target-url');
  230. const url = new URL(links[i].href);
  231. const params = url.searchParams;
  232. siteParams.forEach((k) => { if (params.has(k)) { params.delete(k); } });
  233. Array.from(params.keys()).forEach((k) => { if (biliParamsReg.test(k)) { params.delete(k); } });
  234. if (links[i].href !== url.href) { links[i].href = url.href; }
  235. }
  236. // 3. Bilibili
  237. // Clean <a> link data-url on video/bangumi of bilibili.com
  238. const dataLink = links[i].getAttribute('data-url');
  239. if (/^(https?:\/\/|\/\/)[a-zA-Z0-9-.]{1,128}\.[a-z]{2,15}/.test(dataLink)) {
  240. let dlURL;
  241. if (dataLink.startsWith('//')) {
  242. dlURL = new URL(`https:${dataLink}`);
  243. } else {
  244. dlURL = new URL(dataLink);
  245. }
  246. const dlParams = dlURL.searchParams;
  247. if (dlURL.hostname.endsWith('bilibili.com')) {
  248. Array.from(dlParams.keys()).forEach((k) => { if (biliParamsReg.test(k)) { dlParams.delete(k); } });
  249. siteParams.forEach((k) => { if (dlParams.has(k)) { dlParams.delete(k); } });
  250. } else {
  251. const dlParamsReg = paramsReg;
  252. Array.from(dlParams.keys()).forEach((k) => { if (dlParamsReg.test(k)) { dlParams.delete(k); } });
  253. commonParams.forEach((k) => { if (dlParams.has(k)) { dlParams.delete(k); } });
  254. }
  255. links[i].href = dlURL.href;
  256. links[i].classList.remove('jump-link');
  257. links[i].target = '_blank';
  258. if (links[i].innerText.startsWith(dlURL.href)) {
  259. links[i].innerText = dlURL.href;
  260. }
  261. }
  262. }
  263. };
  264. break;
  265. case /amazon\.[a-z.]{2,15}$/.test(pageHost):
  266. cleanLinks = (siteParams) => {
  267. const links = doc.getElementsByTagName('a');
  268. for (let i = 0; i < links.length; i += 1) {
  269. if (hostRegex.test(links[i].hostname)) {
  270. const url = new URL(links[i].href);
  271. const params = url.searchParams;
  272. siteParams.forEach((k) => { if (params.has(k)) { params.delete(k); } });
  273. Array.from(params.keys()).forEach((k) => { if (amznParamsReg.test(k)) { params.delete(k); } });
  274. if (links[i].href !== url.href) { links[i].href = url.href; }
  275. }
  276. if (/amazon\.[a-z.]{2,15}$/.test(links[i].hostname)) { // 4. Amazon
  277. if (links[i].pathname.includes('/ref')) {
  278. links[i].pathname = links[i].pathname.substring(links[i].pathname.indexOf('/ref'), 1);
  279. }
  280. }
  281. }
  282. };
  283. break;
  284. case /google\.[a-z.]{2,15}$|about.google$/.test(pageHost):
  285. cleanLinks = (siteParams) => {
  286. const links = doc.getElementsByTagName('a'); const iParamsReg = paramsReg;
  287. for (let i = 0; i < links.length; i += 1) {
  288. if (hostRegex.test(links[i].hostname)) {
  289. const url = new URL(links[i].href);
  290. const params = url.searchParams;
  291. siteParams.forEach((k) => { if (params.has(k)) { params.delete(k); } });
  292. Array.from(params.keys()).forEach((k) => { if (iParamsReg.test(k)) { params.delete(k); } });
  293. if (links[i].href !== url.href) { links[i].href = url.href; }
  294. // Clean params at the hash of urls // 5. Google
  295. if (/utm_/.test(url.hash)) {
  296. const ua = url.hash.substring(1).split('&');
  297. ua.forEach((key, index) => { if (/^utm_/.test(key)) ua.splice(index, 8); });
  298. links[i].hash = `#${ua.toString().replaceAll(',', '&')}`;
  299. }
  300. }
  301. }
  302. };
  303. break;
  304. default:
  305. cleanLinks = (siteParams) => {
  306. const links = doc.getElementsByTagName('a'); const iParamsReg = paramsReg;
  307. for (let i = 0; i < links.length; i += 1) {
  308. if (hostRegex.test(links[i].hostname)) {
  309. const url = new URL(links[i].href);
  310. const params = url.searchParams;
  311. siteParams.forEach((k) => { if (params.has(k)) { params.delete(k); } });
  312. Array.from(params.keys()).forEach((k) => { if (iParamsReg.test(k)) { params.delete(k); } });
  313. if (links[i].href !== url.href) { links[i].href = url.href; }
  314. }
  315. }
  316. };
  317. break;
  318. }
  319. function deferredCleanLinks(siteParams, delayTime) {
  320. const tid = setTimeout(() => {
  321. restoreState(siteParams); cleanLinks(siteParams); clearTimeout(tid);
  322. }, delayTime);
  323. }
  324. // Block link clicking events
  325. function blockClickEvents(siteParams, delayTime) {
  326. const tid = setTimeout(() => {
  327. const handleLinkClick = () => { cleanLinks(siteParams); };
  328. const handleLinkCM = (e) => { e.stopImmediatePropagation(); cleanLinks(siteParams); };
  329. const handleLinkClickN = () => { deferredCleanLinks(siteParams, 0); };
  330. const divs = doc.getElementsByTagName('div');
  331. for (let i = 0; i < divs.length; i += 1) {
  332. if (divs[i].className) {
  333. divs[i].removeEventListener('click', handleLinkClickN);
  334. divs[i].addEventListener('click', handleLinkClickN);
  335. divs[i].removeEventListener('auxclick', handleLinkCM);
  336. divs[i].addEventListener('auxclick', handleLinkCM);
  337. divs[i].removeEventListener('mousedown', handleLinkClick);
  338. divs[i].addEventListener('mousedown', handleLinkClick);
  339. divs[i].removeEventListener('keydown', handleLinkClick);
  340. divs[i].addEventListener('keydown', handleLinkClick);
  341. }
  342. }
  343. const btns = doc.getElementsByTagName('button');
  344. for (let i = 0; i < btns.length; i += 1) {
  345. if (btns[i].className) {
  346. btns[i].removeEventListener('click', handleLinkClickN);
  347. btns[i].addEventListener('click', handleLinkClickN);
  348. }
  349. }
  350. const links = doc.getElementsByTagName('a');
  351. for (let i = 0; i < links.length; i += 1) {
  352. if (hostRegex.test(links[i].hostname)) {
  353. // links[i].removeEventListener('mousedown', handleLinkCM); // mail.qq.com/web.telegram.org
  354. // links[i].addEventListener('mousedown', handleLinkCM);
  355. links[i].removeEventListener('keyup', handleLinkCM);
  356. links[i].addEventListener('keyup', handleLinkCM);
  357. links[i].removeEventListener('click', handleLinkClick);
  358. links[i].addEventListener('click', handleLinkClick);
  359. links[i].removeEventListener('auxclick', handleLinkClick);
  360. links[i].addEventListener('auxclick', handleLinkClick);
  361. links[i].removeEventListener('contextmenu', handleLinkCM);
  362. if (links[i].ontouchstart === undefined) {
  363. links[i].addEventListener('contextmenu', handleLinkCM);
  364. }
  365. }
  366. }
  367. clearTimeout(tid);
  368. }, delayTime);
  369. }
  370. // ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦ Custom clean ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦
  371. // Youku, Tudou, Douyin, Amazon
  372. function customClean(siteParams) {
  373. restoreState(siteParams); cleanLinks(siteParams);
  374. let x = 0; let y = 0;
  375. doc.addEventListener('pointermove', (e) => {
  376. if (Math.abs(e.clientX - x) > 20 || Math.abs(e.clientY - y) > 20) {
  377. cleanLinks(siteParams); x = e.clientX; y = e.clientY;
  378. }
  379. });
  380. doc.addEventListener('DOMContentLoaded', () => {
  381. blockClickEvents(siteParams, 0);
  382. });
  383. }
  384. // Hide elements (common)
  385. function hideElement(attrs, intervals, duration, isRemove) {
  386. const intervalID = setInterval(() => {
  387. attrs.forEach((attr) => {
  388. if (document.querySelector(attr)) {
  389. if (!isRemove) {
  390. document.querySelector(attr).style.visibility = 'hidden';
  391. } else {
  392. document.querySelector(attr).remove();
  393. }
  394. }
  395. });
  396. }, intervals);
  397. document.addEventListener('DOMContentLoaded', () => {
  398. const timeoutId = setTimeout(() => {
  399. clearInterval(intervalID); clearTimeout(timeoutId);
  400. }, duration);
  401. });
  402. }
  403. // Auto close (common)
  404. function autoClick(attrs, attrIndex, intervals, duration) {
  405. const intervalID = setInterval(() => {
  406. attrs.forEach((attr) => {
  407. const closeBtn = document.querySelectorAll(attr)[attrIndex];
  408. if (closeBtn) { closeBtn.click(); }
  409. });
  410. }, intervals);
  411. document.addEventListener('DOMContentLoaded', () => {
  412. const timeoutId = setTimeout(() => {
  413. clearInterval(intervalID); clearTimeout(timeoutId);
  414. }, duration);
  415. });
  416. }
  417. // Auto close (mutation observer)
  418. function autoClose(loginWindow, closeButton, loginButton, timeout) {
  419. doc.addEventListener('DOMContentLoaded', () => {
  420. const observer = new MutationObserver((mutations) => {
  421. mutations.forEach((mutation) => {
  422. mutation.addedNodes.forEach((node) => {
  423. if (document.querySelector(loginWindow)) {
  424. if (node.querySelector(closeButton) && !isLogin) {
  425. console.info('Auto Cloesd!');
  426. node.querySelector(closeButton).click();
  427. }
  428. }
  429. });
  430. });
  431. });
  432. observer.observe(doc, { childList: true, subtree: true });
  433. if (isLogin) {
  434. const timeoutID = setTimeout(() => {
  435. loginButton.addEventListener('click', () => {
  436. isLogin = true;
  437. observer.disconnect();
  438. });
  439. clearTimeout(timeoutID);
  440. }, DELAY_TIME.normal * 2);
  441. } else { // Set timeout to disconnect observer whithout login button
  442. const timeoutID = setTimeout(() => {
  443. isLogin = true;
  444. observer.disconnect();
  445. clearTimeout(timeoutID);
  446. }, timeout);
  447. }
  448. });
  449. }
  450. // ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦ Common sites ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦
  451. function commonClean() {
  452. switch (true) { // additional params for certain sites
  453. case /google\.[a-z.]{2,15}$|(about|wellbeing).google/.test(pageHost):
  454. commonParams.push(
  455. 'device',
  456. 'pcampaignid',
  457. 'subid',
  458. 'hl',
  459. 'fg',
  460. 'ved',
  461. 'ei',
  462. 'prev',
  463. 'sig',
  464. 'sca_esv',
  465. 'visit_id',
  466. 'dest_src',
  467. );
  468. break;
  469. case pageHost.endsWith('facebook.com'):
  470. commonParams.push(
  471. 'privacy_mutation_token',
  472. 'ars',
  473. 'helpref',
  474. 'search_session_id',
  475. 'entry_point',
  476. 'campaign_id',
  477. 'nav_source',
  478. 'placement',
  479. 'privacy_source',
  480. '__cft__[0]',
  481. '__tn__',
  482. );
  483. break;
  484. case /(twitter|x)\.com$/.test(pageHost):
  485. commonParams.push('screen_name');
  486. break;
  487. case pageHost.endsWith('reddit.com'):
  488. commonParams.push('embed_host_url', 'actionSource', 'shreddit');
  489. paramsReg = /^(utm_|spm_|from_|ref|track|trk|experiment_d2x_|experiment_mweb)/;
  490. break;
  491. case pageHost.endsWith('linkedin.com'):
  492. commonParams.push( // 'trk' , 'trkInfo'
  493. 'original_referer',
  494. 'origin',
  495. 'upsellOrderOrigin',
  496. 'lipi',
  497. 'desktopBackground',
  498. 'profileFormEntryPoint',
  499. 'entityUrn',
  500. 'veh',
  501. 'miniCompanyUrn',
  502. 'courseSlug',
  503. 'upsellTrk',
  504. 'upsellTrackingId',
  505. 'contextUrn',
  506. 'ct',
  507. 'pt',
  508. 'refId',
  509. 'position',
  510. );
  511. document.addEventListener('DOMContentLoaded', () => {
  512. blockClickEvents(commonParams, 8500);
  513. deferredCleanLinks(commonParams, DELAY_TIME.normal * 2);
  514. });
  515. break;
  516. case pageHost.endsWith('dzen.ru'):
  517. commonParams.push(
  518. 'lang',
  519. 'country_code',
  520. 'rid',
  521. 'clid',
  522. 'stid',
  523. 'issue_tld',
  524. 'parent_rid',
  525. 'persistent_id',
  526. 'story',
  527. 't',
  528. 'utr',
  529. 'place',
  530. 'secdata',
  531. 'integration',
  532. 'feed_exp',
  533. 'force_common_feed',
  534. 'feed_filter_type',
  535. 'feed_filter_source',
  536. );
  537. break;
  538. case pageHost.endsWith('vk.com'):
  539. commonParams.push('scheme', 'initial_stats_info');
  540. break;
  541. case /(microsoft|bing|xbox|skype|office|microsoft365)\.com$/.test(pageHost):
  542. commonParams.push(
  543. 'ocid',
  544. 'OCID',
  545. 'ICID',
  546. 'icid',
  547. 'CLCID',
  548. 'clcid',
  549. 'es',
  550. 'response_mode',
  551. 'exp',
  552. 'form',
  553. 'FORM',
  554. 'xr',
  555. 'cat0',
  556. 'culture',
  557. 'country',
  558. 'WT.mc_id',
  559. 'uiflavor', // office
  560. 'activetab',
  561. 'fl',
  562. 'client_id',
  563. 'wreply',
  564. 'cobrandid', // signin
  565. 'deeplink',
  566. 'referrer',
  567. 'mode',
  568. 'pos',
  569. );
  570. break;
  571. case /msn.(com|cn)$/.test(pageHost): // No effect on the [Shadow Root] elements.
  572. commonParams.push('ocid', 'cvid', 'ei', '.cn', 'fullscreen');
  573. break;
  574. case /bestbuy\.(com|ca)$/.test(pageHost):
  575. commonParams.push(
  576. 'id',
  577. 'ar',
  578. 'cmp',
  579. 'loc',
  580. 'irgwc',
  581. 'mpid',
  582. 'irclickid',
  583. 'intlreferer',
  584. 'intl',
  585. 'browsedCategory',
  586. 'qp',
  587. 'type',
  588. 'usc',
  589. 'iht',
  590. 'ks',
  591. 'sc',
  592. '_dyncharset',
  593. 'icmp',
  594. ); // 'subId1', 'subId2', 'subId3', 'nrtv_cid', 'nrtv_as_src',
  595. paramsReg = /^(utm_|nrtv_|subId)/;
  596. break;
  597. case pageHost.endsWith('github.com'):
  598. commonParams.push('ref_cta', 'ref_loc', 'ref_page');
  599. break;
  600. case pageHost.endsWith('stackoverflow.com'):
  601. paramsReg = /^(utm_|spm_|from_|ref|track|trk|so_)/;
  602. break;
  603. case pageHost.endsWith('pixiv.net'):
  604. commonParams.push('provider');
  605. break;
  606. case pageHost.endsWith('music.apple.com'):
  607. commonParams.push('at', 'ct', 'itscg', 'itsct');
  608. break;
  609. case pageHost.endsWith('zhihu.com'):
  610. commonParams.push(
  611. 'search_source',
  612. 'hybrid_search_source',
  613. 'hybrid_search_extra',
  614. 'utm_psn',
  615. );
  616. autoClose(
  617. '.Modal-content',
  618. '.Modal-closeButton',
  619. doc.querySelector('.AppHeader-profile button'),
  620. 2000,
  621. );
  622. break;
  623. case /(163|126|yeah)\.(com|net)$/.test(pageHost):
  624. commonParams.push('scene', 'session_id', 'fromDlpro', 'dltype');
  625. break;
  626. case pageHost.endsWith('weibo.com'):
  627. commonParams.push(
  628. 'mark_id',
  629. 'entry',
  630. '_rand',
  631. 'sudaref',
  632. 'refer',
  633. 'band_rank',
  634. 'gid',
  635. 'ua',
  636. );
  637. break;
  638. case pageHost.endsWith('qq.com'):
  639. commonParams.push('ADTAG', 'fromSource');
  640. break;
  641. case /ebay\.[a-z.]{2,15}$/.test(pageHost):
  642. commonParams.push(
  643. '_trkparms',
  644. '_trksid',
  645. 'ssPageName',
  646. 'amdata',
  647. 'mc',
  648. 'hash',
  649. 'epid',
  650. 'var',
  651. '_ssn',
  652. 'store_name',
  653. 'requested',
  654. 'itmprp',
  655. 'itmmeta',
  656. );
  657.  
  658. break;
  659. case pageHost.endsWith('jd.com'):
  660. commonParams.splice(commonParams.indexOf('utm_campaign'), 1);
  661. commonParams.push(
  662. 'gx',
  663. 'ad_od',
  664. 'needRecommendFlag',
  665. 'uabt',
  666. 'd',
  667. '_fd',
  668. 'pvid',
  669. 'jxsid',
  670. 'csid',
  671. 'ss_projid',
  672. 'scan_orig',
  673. 'ss_expid',
  674. 'ss_sexpid',
  675. 'ss_ruleid',
  676. 'ss_sruleid',
  677. 'ss_symbol',
  678. 'ss_mtest',
  679. 'sceneval',
  680. );
  681. paramsReg = /^(track|wxa_|spm_|from_)/;
  682. break;
  683. case pageHost.endsWith('yangkeduo.com'):
  684. commonParams.push(
  685. 'gx',
  686. 'ad_od',
  687. 'needRecommendFlag',
  688. 'uabt',
  689. 'd',
  690. 'pxq_secret_key',
  691. 'cpsSignjb_act',
  692. 'launch_pdd',
  693. 'customParameters',
  694. 'duoduo_type',
  695. 'goods_sign',
  696. );
  697. paramsReg = /^(track|from_|utm_|_oak_|_wv|_x_)/;
  698. break;
  699. case /(hoyolab|hoyoverse|mihoyo|miyoushe|mihoyogift)\.com$/.test(pageHost):
  700. // _auth_require _presentation_style _hide_status_bar _landscape _theme _theme_device
  701. commonParams.push('game_version', 'visit_device', 'device_type', 'plat_type');
  702. paramsReg = /^(track|utm|spm_|from_|hyl_|bbs_|mhy_)|_from$/;
  703. (() => {
  704. // /account.(hoyoverse|hoyolab).com$|user.miyoushe.com$/
  705. const css = document.createElement('style');
  706. css.innerText += 'body{overflow: auto !important}';
  707. doc.addEventListener('DOMContentLoaded', () => {
  708. document.head.append(css);
  709. });
  710. })();
  711. customClean(commonParams);
  712. break;
  713. case pageHost.endsWith('douban.com'):
  714. commonParams.push(
  715. 'target_user_id',
  716. 'dcs',
  717. 'dcm',
  718. 'dt_time_source',
  719. 'channel',
  720. 'fullscreen',
  721. 'autorotate',
  722. 'hidenav',
  723. );
  724. break;
  725. case /(imdb|boxofficemojo)\.com$/.test(pageHost):
  726. commonParams.push('rf', 'imdbPageAction', 'u', 'tag');
  727. paramsReg = amznParamsReg;
  728. break;
  729. case pageHost.endsWith('gitee.com'):
  730. (() => {
  731. const intervalID = setInterval(() => {
  732. if (doc.querySelector('.menu.transition.visible')) {
  733. doc.querySelector('.menu.transition.visible').style = 'display: none !important;';
  734. }
  735. }, 50);
  736. document.addEventListener('DOMContentLoaded', () => {
  737. const timeoutId = setTimeout(() => {
  738. clearInterval(intervalID); clearTimeout(timeoutId);
  739. }, 3000);
  740. });
  741. })();
  742. break;
  743. case pageHost.endsWith('xda-developers.com'):
  744. commonParams.push(
  745. 'tag',
  746. 'ascsubtag',
  747. 'asc_refurl',
  748. 'asc_campaign',
  749. 'newsletter_popup',
  750. );
  751. break;
  752. case pageHost.endsWith('cctv.com'):
  753. commonParams.push('toc_style_id');
  754. break;
  755. case pageHost.endsWith('fiverr.com'):
  756. commonParams.push(
  757. 'pckg_id',
  758. 'funnel',
  759. 'context_type',
  760. 'context_alg',
  761. 'imp_id',
  762. 'pos',
  763. 'seller_online',
  764. 'context',
  765. );
  766. break;
  767. case pageHost.endsWith('newegg.com'):
  768. commonParams.push(
  769. 'cm_sp',
  770. 'nextpage',
  771. );
  772. break;
  773. case pageHost.endsWith('theverge.com'):
  774. commonParams.push(
  775. 'u1',
  776. 'tag',
  777. 'ascsubtag',
  778. 'subId1',
  779. 'subId2',
  780. 'subId3',
  781. );
  782. break;
  783. case pageHost.endsWith('bluestacks.com'):
  784. commonParams.push(
  785. 'platform',
  786. 'client_uuid',
  787. 'app_pkg',
  788. 'platform_cloud',
  789. 'preferred_lang',
  790. 'gaCookie',
  791. 'gclid',
  792. 'clickid',
  793. 'msclkid',
  794. 'affiliateId',
  795. 'offerId',
  796. 'transaction_id',
  797. 'aff_sub',
  798. 'first_landing_page',
  799. 'user_id',
  800. 'incompatible',
  801. 'bluestacks_version',
  802. 'referrer',
  803. 'download_page_referrer',
  804. ); // win_version, mac_version, exit_utm_campaign,
  805. // device_memory, device_cpu_cores
  806. paramsReg = /^device_|(_version|utm_campaign)$/;
  807. break;
  808. case pageHost.endsWith('xiaohongshu.com'):
  809. autoClose(
  810. '.login-container',
  811. '.close-button',
  812. doc.querySelector('.login-btn'),
  813. 3700,
  814. );
  815. break;
  816. case pageHost.endsWith('nicovideo.jp'):
  817. commonParams.push(
  818. 'cmnhd_ref',
  819. 'device',
  820. 'site',
  821. 'pos',
  822. );
  823. break;
  824. default: break;
  825. }
  826. const params = commonParams; restoreState(params); cleanLinks(params);
  827. document.addEventListener('DOMContentLoaded', () => {
  828. blockClickEvents(params, 1200);
  829. deferredCleanLinks(params, 1000); deferredCleanLinks(params, 7000);
  830. });
  831. window.onscroll = () => {
  832. const scrolls = doc.documentElement.scrollTop;
  833. if (scrolls - topScroll > 120) { cleanLinks(params); topScroll = scrolls; }
  834. };
  835. return params;
  836. }
  837. // ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦ Bilibili ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦
  838. // Remove Bilibili metadata
  839. function removeBiliMetadData() {
  840. const metas = doc.getElementsByTagName('meta');
  841. for (let i = 0; i < metas.length; i += 1) {
  842. if (metas[i].name === 'spm_prefix') { metas[i].remove(); }
  843. }
  844. }
  845. // Remove Bilibili Annoyances [Login popups, Ads]
  846. function removeBiliAnnoyances(delayTime) {
  847. const tid = setTimeout(() => {
  848. let index = 0;
  849. do {
  850. const cardAds = doc.getElementsByTagName('a');
  851. for (let i = 0; i < cardAds.length; i += 1) {
  852. if (cardAds[i].hostname.endsWith('cm.bilibili.com')) {
  853. cardAds[i].parentNode.removeChild(cardAds[i]);
  854. } // bilibili ads
  855. }
  856. index += 1;
  857. } while (index < 2); // bilibili login tips
  858. const traceDivs = doc.getElementsByClassName('bili-video-card');
  859. for (let i = 0; i < traceDivs.length; i += 1) {
  860. if (traceDivs[i].getAttribute('data-report').includes('tianma.')) {
  861. traceDivs[i].setAttribute('data-report', '0');
  862. } // bilibili ads
  863. }
  864. /**
  865. * *******************************************************
  866. * *******************************************************
  867. */
  868. const rightEntyItems = doc.getElementsByClassName('right-entry-item')
  869. || doc.getElementsByClassName('item');
  870. if (rightEntyItems[0] && rightEntyItems[0].innerText.includes('登录')) {
  871. hideElement(['.lt-row', '.bili-login-card', '.bili-mini-mask',
  872. '.is-bottom', '.v-popover-content', '.unlogin-popover'], 30, 6000, false);
  873. const loginTab = rightEntyItems[0].getElementsByTagName('span')[0];
  874. if (/登录/.test(rightEntyItems[0].innerText) && loginTab) {
  875. loginTab.outerHTML = '<a href="https://passport.bilibili.com/login"'
  876. + ' target="_blank" onmouseup="cleanLinks(bilibiliParams)">登录</a>';
  877. }
  878. } clearTimeout(tid);
  879. doc.getElementById('right-bottom-banner').remove();
  880. }, delayTime);
  881. }
  882. // block clicking events (link, button, li)
  883. function blockBClickEvents() {
  884. const handleBClickBub = (e) => { e.stopImmediatePropagation(); };
  885. function blockBLinkEvents() {
  886. const links = doc.getElementsByTagName('a');
  887. for (let i = 0; i < links.length; i += 1) {
  888. if (links[i].getAttribute('data-video-time') === null && hostRegex.test(links[i].hostname)) {
  889. const isLinkJump = links[i].classList.contains('jump-link');
  890. const isLinkJumpVideo = links[i].classList.contains('video-time')
  891. || links[i].classList.contains('video');
  892. if (!(isLinkJump && isLinkJumpVideo)) {
  893. if (pageHost.endsWith('bilibili.com')) {
  894. links[i].removeEventListener('click', handleBClickBub);
  895. links[i].addEventListener('click', handleBClickBub);
  896. }
  897. links[i].removeEventListener('contextmenu', handleBClickBub);
  898. if (links[i].ontouchstart === undefined) {
  899. links[i].addEventListener('contextmenu', handleBClickBub);
  900. }
  901. links[i].removeEventListener('pointerdown', handleBClickBub);
  902. links[i].addEventListener('pointerdown', handleBClickBub);
  903. }
  904. }
  905. }
  906. }
  907. blockBLinkEvents();
  908.  
  909. function deferredBlockBLinkEvents(delayTime) {
  910. const tid = setTimeout(() => {
  911. cleanLinks(bilibiliParams); removeBiliAnnoyances(0); blockBLinkEvents(); clearTimeout(tid);
  912. }, delayTime);
  913. }
  914. const handleClickFast = () => { deferredBlockBLinkEvents(DELAY_TIME.fast); };
  915. const buttons = doc.getElementsByTagName('button');
  916. for (let i = 0; i < buttons.length; i += 1) {
  917. if (buttons[i].className) {
  918. buttons[i].removeEventListener('click', handleClickFast);
  919. buttons[i].addEventListener('click', handleClickFast);
  920. }
  921. }
  922. const lines = doc.getElementsByTagName('li');
  923. for (let i = 0; i < lines.length; i += 1) {
  924. if (lines[i].className && !lines[i].classList.contains('context-sub-menu-item')) {
  925. lines[i].removeEventListener('click', handleClickFast);
  926. lines[i].addEventListener('click', handleClickFast);
  927. }
  928. }
  929. // iframe - live
  930. if (pageURL.startsWith('https://live.bilibili.com/blackboard/dropdown')) {
  931. document.addEventListener('DOMContentLoaded', () => {
  932. document.addEventListener('click', (e) => { e.stopPropagation(); }, true);
  933. });
  934. }
  935. }
  936. function deferredBlockBClickEvents(delayTime) {
  937. restoreState(bilibiliParams);
  938. const tid = setTimeout(() => { blockBClickEvents(); clearTimeout(tid); }, delayTime);
  939. }
  940. // Loop execution when the mouse moves
  941. function bilibiliListenMoving() {
  942. let x = 0; let y = 0;
  943. if (/live.bilibili.com$/.test(pageHost)
  944. || /^https?:\/\/(www|m).bilibili\.com\/(video|bangumi)/.test(pageURL)) {
  945. window.onpointermove = (e) => {
  946. if (e.clientY < 200) {
  947. cleanLinks(bilibiliParams);
  948. blockBClickEvents();
  949. }
  950. };
  951. } else {
  952. window.onpointermove = (e) => {
  953. if (Math.abs(e.clientX - x) > 20 || Math.abs(e.clientY - y) > 20) {
  954. cleanLinks(bilibiliParams);
  955. blockBClickEvents();
  956. x = e.clientX; y = e.clientY;
  957. }
  958. };
  959. }
  960. }
  961. // Loop execution when scrolling
  962. function biliListenScrolling() {
  963. window.onscroll = () => {
  964. const scrolls = doc.documentElement.scrollTop;
  965. if (scrolls - topScroll > 120) {
  966. cleanLinks(bilibiliParams);
  967. removeBiliAnnoyances(0);
  968. blockBClickEvents();
  969. topScroll = scrolls;
  970. }
  971. };
  972. }
  973. // bilibili search events
  974. function blockBSearchItemEvents() {
  975. function blockSearchEvents() {
  976. // input suggested items
  977. const suggestItems = doc.getElementsByClassName('suggest-item');
  978. const handleBSearchClick = () => { deferredBlockBClickEvents(DELAY_TIME.fast); };
  979. if (suggestItems) {
  980. for (let i = 0; i < suggestItems.length; i += 1) {
  981. suggestItems[i].addEventListener('click', handleBSearchClick, true);
  982. }
  983. }
  984. // search trending items
  985. const topSearchs = doc.getElementsByClassName('trending-item');
  986. if (topSearchs) {
  987. for (let i = 0; i < topSearchs.length; i += 1) {
  988. topSearchs[i].addEventListener('click', handleBSearchClick, true);
  989. }
  990. }
  991. // search history items
  992. const historyItems = doc.getElementsByClassName('history-item');
  993. if (historyItems) {
  994. for (let i = 0; i < historyItems.length; i += 1) {
  995. historyItems[i].addEventListener('click', handleBSearchClick, true);
  996. }
  997. }
  998. }
  999. const handleBSearchClickB = () => {
  1000. const tid = setTimeout(() => { blockSearchEvents(); clearTimeout(tid); }, DELAY_TIME.fast);
  1001. };
  1002. // search input area
  1003. if (doc.querySelector('.search-input-el')) {
  1004. doc.querySelector('.search-input-el').addEventListener('click', handleBSearchClickB, true);
  1005. }
  1006. // clear icon
  1007. if (doc.querySelector('.clear-icon')) {
  1008. doc.querySelector('.clear-icon').addEventListener('click', handleBSearchClickB, true);
  1009. }
  1010. }
  1011. // search.bilibili.com/*
  1012. function cleanBSearch() {
  1013. blockBSearchItemEvents();
  1014. // paging button clicking event
  1015. const pageButtons = doc.getElementsByClassName('vui_pagenation--btn'); // div
  1016. if (pageButtons) {
  1017. for (let i = 0; i < pageButtons.length; i += 1) {
  1018. pageButtons[i].addEventListener('click', () => { deferredBlockBClickEvents(DELAY_TIME.fast); }, true);
  1019. }
  1020. }
  1021. deferredBlockBClickEvents(DELAY_TIME.normal); deferredCleanLinks(bilibiliParams, DELAY_TIME.slow - 600);
  1022. }
  1023. // www.bilibili.com/video/*
  1024. function cleanBVideoURL() {
  1025. cleanLinks(bilibiliParams);
  1026. doc.addEventListener('DOMContentLoaded', () => {
  1027. if (doc.querySelector('.rec-footer')) {
  1028. doc.querySelector('.rec-footer').addEventListener('click', () => {
  1029. deferredCleanLinks(bilibiliParams, DELAY_TIME.fast);
  1030. deferredBlockBClickEvents(bilibiliParams, DELAY_TIME.fast);
  1031. }, true);
  1032. }
  1033. // Clean copying of video URLs (copy share)
  1034. let toolBar; let sharInner; let sharOuter;
  1035. if (/^\/video\//.test(pagePath)) {
  1036. toolBar = '#arc_toolbar_report'; sharOuter = 'share-btn-outer'; sharInner = 'share-btn-inner';
  1037. } else if (/^\/bangumi\//.test(pagePath)) {
  1038. toolBar = '.toolbar'; sharOuter = 'share-container-id'; sharInner = 'link_copy';
  1039. }
  1040. let vid; const url = new URL(window.location.href);
  1041. const handleWriteText = () => { navigator.clipboard.writeText(pageURL); };
  1042. if (doc.querySelector(toolBar)) {
  1043. doc.querySelector(toolBar).addEventListener('pointermove', () => {
  1044. if (doc.getElementById(sharOuter)) {
  1045. doc.getElementById(sharOuter).removeEventListener('click', handleWriteText);
  1046. doc.getElementById(sharOuter).addEventListener('click', handleWriteText);
  1047. doc.getElementById(sharInner).addEventListener('click', (event) => {
  1048. event.stopImmediatePropagation();
  1049. if (doc.getElementById(sharInner).innerText.includes('精准')) {
  1050. if (pagePath.indexOf('/video/') === 0) {
  1051. vid = doc.querySelector('video') || doc.querySelector('bwp-video'); // Chrome Firefox Edge ..
  1052. } else if (pagePath.indexOf('/bangumi/') === 0) {
  1053. vid = doc.getElementsByTagName('video')[1] || doc.querySelector('bwp-video');
  1054. }
  1055. url.searchParams.set('t', vid.currentTime.toFixed(2));
  1056. navigator.clipboard.writeText(url.toString());
  1057. } else { navigator.clipboard.writeText(pageURL); }
  1058. });
  1059. }
  1060. });
  1061. }
  1062. });
  1063. }
  1064. // live.bilibili.com/*
  1065. function cleanBLive(delayTime) {
  1066. // live.bilibili.com popups
  1067. const livePopupBlock = (selection) => {
  1068. if (selection && doc.getElementById('anchor-guest-box-id')) {
  1069. doc.getElementById('anchor-guest-box-id').style.display = 'none';
  1070. } else if (!selection) {
  1071. doc.getElementById('anchor-guest-box-id').style.display = '';
  1072. }
  1073. const iframes = doc.getElementsByTagName('iframe');
  1074. for (let i = 0; i < iframes.length; i += 1) {
  1075. if (iframes[i].src.includes('live-lottery')) {
  1076. if (selection) {
  1077. iframes[i].style.visibility = 'hidden';
  1078. } else {
  1079. iframes[i].style.visibility = '';
  1080. }
  1081. }
  1082. }
  1083. };
  1084. const tid1 = setTimeout(() => {
  1085. const navis = doc.getElementsByClassName('tabs__tag-item'); // cat
  1086. if (navis) {
  1087. for (let i = 0; i < navis.length; i += 1) {
  1088. navis[i].addEventListener('click', () => {
  1089. deferredCleanLinks(bilibiliParams, DELAY_TIME.fast);
  1090. }, true);
  1091. }
  1092. }
  1093. const tabItems = doc.getElementsByClassName('tab-item'); // sort
  1094. if (tabItems) {
  1095. for (let i = 0; i < tabItems.length; i += 1) {
  1096. tabItems[i].addEventListener('click', () => {
  1097. blockBClickEvents();
  1098. deferredCleanLinks(bilibiliParams, DELAY_TIME.fast);
  1099. }, true);
  1100. }
  1101. } clearTimeout(tid1);
  1102. }, delayTime);
  1103. const intervalID = setInterval(
  1104. livePopupBlock(BlockLivePopups),
  1105. DELAY_TIME.normal * 2,
  1106. );
  1107. const tid2 = setTimeout(() => {
  1108. clearInterval(intervalID);
  1109. clearTimeout(tid2);
  1110. }, DELAY_TIME.slow + 3000 * 300);
  1111. }
  1112. // ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦ Baidu ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦
  1113. // Baidu related search, Hot search URL cleaning
  1114. function cleanBaidu() {
  1115. if (pageHost.endsWith('news.baidu.com')) {
  1116. baiduParams.push('toc_style_id', 'share_to', 'track_id');
  1117. }
  1118. restoreState(baiduParams);
  1119. function removeBDAds() {
  1120. const searchAds = document.getElementsByClassName('EC_result');
  1121. if (searchAds) {
  1122. for (let i = 0; i < searchAds.length; i += 1) {
  1123. searchAds[i].remove();
  1124. }
  1125. }
  1126. }
  1127. if (pageHost.endsWith('tieba.baidu.com') && baiduParams.includes('ie')) {
  1128. baiduParams.splice(baiduParams.indexOf('ie'), 1);
  1129. }
  1130. function cleanBDLinks(siteParams) {
  1131. cleanLinks(baiduParams);
  1132. const links = doc.getElementsByTagName('a');
  1133. for (let i = 0; i < links.length; i += 1) {
  1134. if (hostRegex.test(links[i].hostname)) {
  1135. if (links[i].hostname.endsWith('zhidao.baidu.com') && links[i].pathname === '/q') {
  1136. links[i].pathname = '/search';
  1137. }
  1138. links[i].href = links[i].href.replace('from=', '');
  1139. }
  1140. }
  1141. if (doc.querySelector('area')) {
  1142. const areaURL = new URL(doc.querySelector('area').href);
  1143. const params = areaURL.searchParams;
  1144. siteParams.forEach((k) => {
  1145. if (params.has(k)) { params.delete(k); }
  1146. });
  1147. doc.querySelector('area').href = areaURL.href;
  1148. }
  1149. }
  1150. function blockBDTrackingEvents() {
  1151. doc.addEventListener('DOMContentLoaded', () => {
  1152. const links = doc.getElementsByTagName('a');
  1153. for (let i = 0; i < links.length; i += 1) {
  1154. if (links[i].href !== '') {
  1155. links[i].addEventListener('click', () => {
  1156. cleanBDLinks(baiduParams);
  1157. }, true);
  1158. }
  1159. }
  1160. });
  1161. }
  1162. cleanBDLinks(baiduParams); blockBDTrackingEvents();
  1163. if (pagePath === '/s') removeBDAds();
  1164. window.onscroll = () => {
  1165. const scrolls = doc.documentElement.scrollTop;
  1166. if (scrolls - topScroll > 120) {
  1167. cleanLinks(baiduParams); topScroll = scrolls;
  1168. }
  1169. if (pagePath === '/s') { removeBDAds(); } // Baidu search ads
  1170. };
  1171. let x = 0; let y = 0;
  1172. window.onpointermove = (e) => {
  1173. if (Math.abs(e.clientX - x) > 20 || Math.abs(e.clientY - y) > 20) {
  1174. cleanLinks(baiduParams); x = e.clientX; y = e.clientY;
  1175. }
  1176. };
  1177. }
  1178. // ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦ CSDN ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦
  1179. function cleanCSDN() {
  1180. restoreState(csdnParams); deferredCleanLinks(csdnParams, DELAY_TIME.normal);
  1181. // CSDN.net tracking events
  1182. function blockCSDNEvents() {
  1183. const links = doc.getElementsByTagName('a');
  1184. for (let i = 0; i < links.length; i += 1) {
  1185. if (links[i].hostname) {
  1186. links[i].addEventListener('click', (e) => {
  1187. e.stopImmediatePropagation();
  1188. });
  1189. }
  1190. }
  1191. }
  1192. window.onpointermove = (e) => {
  1193. if (e.clientY < 170 || e.clientY > 450) {
  1194. cleanLinks(csdnParams); blockCSDNEvents();
  1195. }
  1196. };
  1197. window.onscroll = () => {
  1198. const scrolls = doc.documentElement.scrollTop;
  1199. if (scrolls - topScroll > 120) {
  1200. cleanLinks(csdnParams);
  1201. blockCSDNEvents(); topScroll = scrolls;
  1202. }
  1203. };
  1204. }
  1205. // ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦ Ali Sites ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦
  1206. function cleanAliSites() {
  1207. switch (true) { // taobao.com/tmall.com/tmall.hk
  1208. case /(taobao|tmall).(com|hk)$/.test(pageHost):
  1209. aliParams.push(
  1210. 'scm2',
  1211. 'stats_click',
  1212. 'initiative_id',
  1213. 'source',
  1214. 'suggest',
  1215. 'suggest_query',
  1216. 'iconType',
  1217. 'traceId',
  1218. 'relationId',
  1219. 'union_lens',
  1220. 'ref',
  1221. 'ali_trackid',
  1222. 'ak',
  1223. 'detailSharePosition',
  1224. 'topOfferIds',
  1225. 'sp_abtk',
  1226. 'search_condition',
  1227. 'industryCatId',
  1228. 'tbSocialPopKey',
  1229. 'bxsign',
  1230. 'utparam',
  1231. 'eurl',
  1232. 'itemIds',
  1233. 'country',
  1234. 'epid',
  1235. 'user_number_id',
  1236. 'rootPageId',
  1237. 'lwfrom',
  1238. 'disableNav',
  1239. 'es',
  1240. 'rand',
  1241. '_lgt_',
  1242. 'x5referer',
  1243. 'status_bar_transparent',
  1244. 'tracelog',
  1245. );
  1246. break;
  1247. case pageHost.endsWith('fliggy.com'):
  1248. aliParams.push('ad_id', 'am_id', 'cm_id', 'pm_id', '_k');
  1249. break;
  1250. case pageHost.endsWith('1688.com'):
  1251. aliParams.push(
  1252. 'scm2',
  1253. 'topOfferIds',
  1254. '__pageId__',
  1255. 'resourceId',
  1256. 'offerId',
  1257. 'offerIds',
  1258. 'object_id',
  1259. 'udsPoolId',
  1260. 'resultType',
  1261. 'cms_id',
  1262. 'pha_html',
  1263. '__existtitle__',
  1264. 'object_type',
  1265. 'delivery_pool_id',
  1266. 'delivery_pool_type',
  1267. 'ilike_session',
  1268. 'tracelog',
  1269. 'clickid',
  1270. 'sessionid',
  1271. 'cosite',
  1272. '_p_isad',
  1273. 'exp',
  1274. 'rootPageId',
  1275. 'lwfrom',
  1276. 'disableNav',
  1277. 'es',
  1278. 'hpageId',
  1279. );
  1280. break;
  1281. case /(lazada|trendyol).[a-z.]{2-10}/.test(pageHost):
  1282. aliParams.push(
  1283. 'shareUniqueId',
  1284. 'clickTrackInfo',
  1285. 'data_prefetch',
  1286. 'at_iframe',
  1287. 'prefetch_replace',
  1288. 'wc',
  1289. );
  1290. break;
  1291. default: break;
  1292. }
  1293. restoreState(aliParams);
  1294. deferredCleanLinks(aliParams, DELAY_TIME.slow);
  1295. doc.addEventListener('DOMContentLoaded', () => {
  1296. blockClickEvents(aliParams, DELAY_TIME.fast);
  1297. });
  1298. window.onscroll = () => {
  1299. const scrolls = doc.documentElement.scrollTop;
  1300. if (scrolls - topScroll > 120) {
  1301. cleanLinks(aliParams);
  1302. blockClickEvents(aliParams, 0); topScroll = scrolls;
  1303. }
  1304. };
  1305. }
  1306. // ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦ Youtube ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦
  1307. function cleanYoutube() {
  1308. function blockytLinksRedirection(timeout) {
  1309. setTimeout(() => {
  1310. const outerLinks = document.getElementsByClassName('yt-core-attributed-string--link-inherit-color');
  1311. for (let i = 0; i < outerLinks.length; i += 1) {
  1312. outerLinks[i].addEventListener('click', (e) => {
  1313. e.stopPropagation();
  1314. }, true);
  1315. }
  1316. }, timeout);
  1317. }
  1318. restoreState(ytParams); cleanLinks(ytParams);
  1319. doc.addEventListener('DOMContentLoaded', () => {
  1320. deferredCleanLinks(ytParams, DELAY_TIME.slow);
  1321. blockClickEvents(ytParams, 0);
  1322. blockytLinksRedirection(DELAY_TIME.normal * 2);
  1323. });
  1324. doc.addEventListener('contextmenu', () => {
  1325. cleanLinks(ytParams);
  1326. if (pagePath === '/results') {
  1327. doc.addEventListener('pointerenter', (e) => {
  1328. e.stopPropagation();
  1329. cleanLinks(ytParams);
  1330. }, true);
  1331. }
  1332. window.onscroll = () => {
  1333. const scrolls = doc.documentElement.scrollTop;
  1334. if (scrolls - topScroll > 120) {
  1335. cleanLinks(ytParams);
  1336. blockytLinksRedirection(0);
  1337. topScroll = scrolls;
  1338. }
  1339. };
  1340. // Modifications for CM of youtube player
  1341. const shareURL = new URL('https://youtube.com/watch');
  1342. if (new URL(pageURL).searchParams.has('list')) {
  1343. shareURL.searchParams
  1344. .set('list', new URL(pageURL).searchParams.get('list'));
  1345. }
  1346. if (pagePath.startsWith('/watch')) {
  1347. shareURL.searchParams.set('v', new URL(pageURL).searchParams.get('v'));
  1348. const videoCM = doc.getElementsByClassName('ytp-contextmenu')[0]
  1349. .getElementsByClassName('ytp-menuitem');
  1350. videoCM[1].addEventListener('click', () => {
  1351. navigator.clipboard.writeText(shareURL.href);
  1352. });
  1353. videoCM[2].addEventListener('click', () => {
  1354. shareURL.searchParams.set(
  1355. 't',
  1356. doc.getElementsByTagName('video')[0].currentTime.toFixed(0),
  1357. );
  1358. navigator.clipboard.writeText(shareURL.href);
  1359. });
  1360. }
  1361. if (pagePath.startsWith('/embed')) { // Embedded youtube videos
  1362. shareURL.searchParams.set('v', pagePath.replace('/embed/', ''));
  1363. const videoCM = doc.getElementsByClassName('ytp-contextmenu')[0]
  1364. .getElementsByClassName('ytp-menuitem');
  1365. videoCM[2].addEventListener('click', () => {
  1366. navigator.clipboard.writeText(shareURL.href);
  1367. });
  1368. videoCM[3].addEventListener('click', () => {
  1369. shareURL.searchParams.set(
  1370. 't',
  1371. doc.getElementsByTagName('video')[0].currentTime.toFixed(0),
  1372. );
  1373. navigator.clipboard.writeText(shareURL.href);
  1374. });
  1375. }
  1376. });
  1377. }
  1378. // ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦ Main Function ✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦✦
  1379. (() => {
  1380. // Menu language (May not change properly due to browser settings)
  1381. let MenuClean; let MenuAddParams; let InputTitle; let invalidFormat;
  1382. let MenuRemoveParam; let noSuchParam; let addedParamsMenu;
  1383. let noCustomParamPrompt;
  1384. switch (navigator.language) {
  1385. case 'zh-CN' || 'zh-SG':
  1386. MenuClean = '手动清理链接';
  1387. MenuAddParams = '添加自定义参数(半角英文模式)';
  1388. InputTitle = '请输入单个指定的参数(仅支持字母,数字,下划线,短破折号(-)与任意类型的括号)';
  1389. invalidFormat = '无效的参数格式 ';
  1390. MenuRemoveParam = '移除一个手动添加的参数(页面刷新后生效)';
  1391. noSuchParam = '无此参数';
  1392. addedParamsMenu = '已添加的自定义参数\n\n';
  1393. noCustomParamPrompt = '暂未添加任何的自定义参数';
  1394. break;
  1395. case 'zh-TW' || 'zh-HK':
  1396. MenuClean = '手動清理鏈接';
  1397. MenuAddParams = '添加自定義参数(半角英文模式)';
  1398. InputTitle = '請輸入單個指定的參數(僅支持字母,數字,下劃線,短破折號(-)與任意類型的括號)';
  1399. invalidFormat = '無效的參數格式 ';
  1400. MenuRemoveParam = '移除一個手動添加的參數(頁面刷新後生效)';
  1401. noSuchParam = '無此參數';
  1402. addedParamsMenu = '已添加的自定義參數\n\n';
  1403. noCustomParamPrompt = '暫未添加任何的自定義參數';
  1404. break;
  1405. default: // English and others
  1406. MenuClean = 'Retry link cleaning';
  1407. MenuAddParams = 'Add a custom parameter (English Mode)';
  1408. InputTitle = 'Please enter a single parameter below \n(only support '
  1409. + 'letters, numbers, underscore, en-dash and all types of brackets):';
  1410. invalidFormat = 'Not a valid parameter format ';
  1411. MenuRemoveParam = 'Remove a custom parameter (Effect after refresh)';
  1412. noSuchParam = 'No such parameter.';
  1413. addedParamsMenu = 'Get all custom added params:\n\n';
  1414. noCustomParamPrompt = 'No added custom parameters now!';
  1415. break;
  1416. } // -._~:/?#[]@!$&'()*+,;=
  1417. // Add custom params from the Script menu (Submenu of addons)
  1418. function addCustomParam(inputParam, storedArray) {
  1419. if (/^[a-zA-Z0-9()[\]{}<>_-]*$/.test(inputParam)) {
  1420. let list; // eslint-disable-next-line no-undef
  1421. if (GM_getValue(pageHost)) { // eslint-disable-next-line no-undef
  1422. list = GM_getValue(pageHost);
  1423. } else {
  1424. list = [];
  1425. } // eslint-disable-next-line no-undef
  1426. if (inputParam) { list.push(inputParam); GM_setValue(pageHost, list); }
  1427. list.forEach((v) => {
  1428. if (!storedArray.includes(v)) { storedArray.push(v); }
  1429. });
  1430. } else {
  1431. alert(invalidFormat);
  1432. }
  1433. }
  1434. // get all custom added param
  1435. function getCustomParams() {
  1436. let list; // eslint-disable-next-line no-undef
  1437. if (GM_getValue(pageHost)) { // eslint-disable-next-line no-undef
  1438. list = GM_getValue(pageHost);
  1439. } else {
  1440. list = [];
  1441. } // eslint-disable-next-line no-undef
  1442. return list;
  1443. }
  1444. // Remove a parameter that has been added from the script menu
  1445. function removeCustomAddedParam(inputParam) {
  1446. if (inputParam !== null && inputParam !== undefined) {
  1447. let list; // eslint-disable-next-line no-undef
  1448. if (GM_getValue(pageHost)) { // eslint-disable-next-line no-undef
  1449. list = GM_getValue(pageHost);
  1450. } else {
  1451. list = [];
  1452. }
  1453. if (list.includes(inputParam)) {
  1454. list = list.filter((item) => item !== inputParam); // eslint-disable-next-line no-undef
  1455. GM_setValue(pageHost, list);
  1456. } else {
  1457. alert(noSuchParam);
  1458. }
  1459. }
  1460. }
  1461. let siteParams;// For script menu
  1462. switch (true) {
  1463. case pageHost.endsWith('youtube.com'):
  1464. siteParams = ytParams; cleanYoutube(siteParams);
  1465. break;
  1466. case pageHost.endsWith('baidu.com'):
  1467. siteParams = baiduParams; cleanBaidu(); cleanLinks(baiduParams);
  1468. break;
  1469. case /amazon\.[a-z.]{2,15}$/.test(pageHost):
  1470. siteParams = amaznParams; paramsReg = amznParamsReg;
  1471. customClean(siteParams, paramsReg);
  1472. break; // REST: space passport account message member t app manga show link biligame mall pay
  1473. case /(bilibili|biligame)\.com$/.test(pageHost): // && pagePath !== '/mall/upower-pay/'
  1474. siteParams = bilibiliParams; paramsReg = biliParamsReg;
  1475. restoreState(bilibiliParams);
  1476. cleanLinks(bilibiliParams);
  1477. blockBClickEvents();
  1478.  
  1479. if (pageHost.endsWith('www.bilibili.com')) cleanBVideoURL();
  1480. if (pageHost.endsWith('search.bilibili.com')) cleanBSearch();
  1481. if (pageHost.endsWith('live.bilibili.com')) cleanBLive(DELAY_TIME.normal);
  1482. doc.addEventListener('DOMContentLoaded', () => {
  1483. biliListenScrolling(); bilibiliListenMoving();
  1484. removeBiliMetadData();
  1485. deferredBlockBClickEvents(1000);
  1486. });
  1487. break;
  1488. case aliSitesReg.test(pageHost):
  1489. siteParams = aliParams; paramsReg = aliParamsReg;
  1490. cleanAliSites();
  1491. break;
  1492. case pageHost.endsWith('csdn.net'):
  1493. siteParams = csdnParams; cleanCSDN();
  1494. break;
  1495. case /(youku|tudou)\.com$/.test(pageHost):
  1496. siteParams = youkuTudouParams; paramsReg = aliParamsReg;
  1497. customClean(siteParams);
  1498. break;
  1499. case /(tiktok|douyin)\.com$/.test(pageHost):
  1500. siteParams = douyinParams; customClean(siteParams);
  1501. // '#login-pannel', '.dy-account-close',
  1502. break;
  1503. default:
  1504. siteParams = commonClean();
  1505. break;
  1506. }
  1507. addCustomParam('', siteParams);
  1508. // show all custom added param
  1509. function showCustomParams() {
  1510. const list = getCustomParams(siteParams);
  1511. if (list.length > 0) {
  1512. alert(addedParamsMenu + list.join(', '));
  1513. } else {
  1514. alert(noCustomParamPrompt);
  1515. }
  1516. } // eslint-disable-next-line no-undef
  1517. GM_registerMenuCommand(MenuClean, () => { // Menu: Retry clean all links
  1518. restoreState(siteParams);
  1519. cleanLinks(siteParams);
  1520. console.log(baiduParams);
  1521. }, 'C');
  1522. // eslint-disable-next-line no-undef
  1523. GM_registerMenuCommand(MenuAddParams, () => { // Menu: Add a custom param
  1524. addCustomParam(prompt(InputTitle, ''), siteParams);
  1525. });
  1526. // eslint-disable-next-line no-undef
  1527. GM_registerMenuCommand(MenuRemoveParam, () => { // Menu: Remove a custom param
  1528. const list = getCustomParams(siteParams);
  1529. if (list.length > 0) {
  1530. const inputParam = prompt(`${addedParamsMenu + list.join(', ')}`, '');
  1531. removeCustomAddedParam(inputParam);
  1532. } else {
  1533. alert(noCustomParamPrompt);
  1534. }
  1535. });
  1536. // eslint-disable-next-line no-undef
  1537. GM_registerMenuCommand(addedParamsMenu, showCustomParams);
  1538.  
  1539. window.addEventListener('urlchange', () => {
  1540. restoreState(siteParams);
  1541. cleanLinks(siteParams);
  1542. blockClickEvents(siteParams, 0);
  1543. });
  1544. window.addEventListener('keydown', (e) => { // [Alt + Shift + X]
  1545. if (e.key === 'X' && e.altKey && e.shiftKey) {
  1546. restoreState(siteParams);
  1547. cleanLinks(siteParams);
  1548. if (pageHost.includes('bilibili.com')) removeBiliAnnoyances(0);
  1549. }
  1550. });
  1551. })();
  1552. })();
  1553.  
  1554. /*
  1555. # Changelog
  1556. v0.7.8 2024.09.27
  1557. - Clear more tracking elements on bilibili|nicovideo|google|microsoft|ebay.
  1558. - Optimised the clean condtions on baidu search result.
  1559. - Various script optimisations.
  1560. - Add some menus to get or delete custom added params. (Thanks to @JerryYang-30)
  1561.  
  1562. v0.7.7 2024.03.21
  1563. - Fix some issues on douyin.com|hoyolab.com under certain conditions.
  1564. - Fix an issus that this script may keep preventing users to pay for bili ups.
  1565. - Certain functions optimisations.
  1566.  
  1567. v0.7.6.2 2024.03.14
  1568. - Fix an issue that certain pages of bilibili may not be functional.
  1569.  
  1570. v0.7.6.1 2024.03.12
  1571. - Fix an issue that certain pages of bilibili may not be functional.
  1572.  
  1573. v0.7.6 2024.03.12
  1574. - Clean more parameters on google.com.
  1575. - Remove a banner ad on bilibili's video page.
  1576. - Adjust cleanup scope on t.bilibili.com.
  1577. - Fix an issue that some contents may not be loaded properly on Zhihu or other sites.
  1578.  
  1579. v0.7.5 2023.11.21
  1580. - Resotore necessary parameters for baidu.com|qq.com in some cases.
  1581. - Minor adjustments.
  1582.  
  1583. v0.7.4 2023.10.22
  1584. - Clean more tracking parameters on 1688|microsoft|linkedin|bluestacks.com and for all.
  1585. - Skip the links redirection on youtube video.
  1586. - Minor improvements.
  1587.  
  1588. v0.7.3 2023.09.28
  1589. - Clean more tracking parameters on (newegg|bestbuy|skype|office|microsoft365|douban).com.
  1590. - Minor issue fixes.
  1591.  
  1592. v0.7.2 2023.09.16
  1593. - Fixed an issue that some prompts unable to close on live.bilibili.com.
  1594. - Fixed an issue that some contents may not be loaded properly.
  1595. - Fixed an issue that certain login prompts may failed to popup.
  1596.  
  1597. v0.7.1 2023.09.10
  1598. - Restore the essential parameters for discord callbacks.
  1599. - Clean more parameters.
  1600.  
  1601. v0.7.0 2023.09.08
  1602. - Clean more tracking params on bestbuy|amazon|baidu|douyin|ebay|jd.
  1603. - Improves the performance on ali sites.
  1604. - Minor issues fixes and improvements.
  1605.  
  1606. v0.6.12 2023.08.28
  1607. - Minor optimisations to be compatible with page adjustments of zhihu.com.
  1608.  
  1609. v0.6.11 2023.08.24
  1610. - Fixed an issue when preventing certain events may cause parts of the page malfunctional.
  1611. - Fixed an issue that some contents on the video page of bilibili failed to load.
  1612. - Minor issues fixes.
  1613.  
  1614. v0.6.10 2023.08.19
  1615. - Fix an issue where the CM for soem sites may fail to prompt in mobile-view mode.
  1616.  
  1617. v0.6.9 2023.08.15
  1618. - Clean more parameters common, (bilibili|1688|taobao|pixiv|fiverr).
  1619. - Improve performance on ali sites (reduce regex mathcing words).
  1620. - Minor issues fixes and performance improvments.
  1621.  
  1622. v0.6.8 2023.07.02
  1623. - Temporarily hide annoying content on `gitee.com`.
  1624. - Clean more parameters for ali sties includes `jiyoujia|fliggy.com`.
  1625. - Minor issuss fixes and performance improvemets.
  1626.  
  1627. v0.6.7 2023.06.24
  1628. - Clean more parameters for `all|dzen.ru|yangkeduo.com|imdb|boxofficemojo|qq|bilibili.com`.
  1629. - Clean all parameters whose names match `^spm|scm`, optimised the regexp matching.
  1630. - Allow using en-dash `(-)` on the function of add custom parameters.
  1631. - Performance improvements.
  1632.  
  1633. v0.6.6.1 2023.06.15
  1634. - Fixed an issue where the missing existence detection for bilibili may cause numerous error messages (Check before use).
  1635.  
  1636. v0.6.6 2023.06.15
  1637. - Remove more tracking parameters on `Amazon|LinkedIn.com|ebay|Youtube.com|Imdb|Bilibili|Apple.com` and common parameters.
  1638. - Allow adding custom parameters to the websites that in additional cleaning.
  1639. - Block more tracking events within its iframe, remove ad-links`(right-bottom-banner|bannerAd)` on bilibili.com.
  1640. - Performance improvements and issue fixes.
  1641.  
  1642. v0.6.5 2023.06.07
  1643. - Clean more tracking params on `Google|Bilibili|Youtube|Stackoverflow|Bing.com|Xbox.com|Facebook|Amazon`, block more tracking events.
  1644. - Clean tracking params at the hash of URLs on `Google`.
  1645. - Allow using numbers and other types of brackets on the function of add custom parameters.
  1646. - More precise domain name matching. (function includes() >> startsWith/endsWith/Regular Expression).
  1647. - Fix most timeout issues, and other issue fixes and performance improvements (events listening optimisations).
  1648. - Additional feature: hide login popups for `zhihu.com|hoyolab.com`.
  1649.  
  1650. v0.6.4 2023.06.02
  1651. - Reduce event blocking scope that binds to the elements `<a>` (capturing >> bubbling).
  1652. - Clean more tracking params on `linkedin|tmall|facebook|google|ebay.com`, block tracking events on `linkedin.com`.
  1653. - Clean copying of video urls after right-click at the main video on `youtube.com` (unshorten without tracking params).
  1654. - Other improvements.
  1655.  
  1656. v0.6.3 2023.05.26
  1657. - Description optimisation (Script menu).
  1658. - Script optimisation, update excludes.
  1659. - Remove more parameters for `Amazon, Taobao, Reddit`, bilibili.com/bangumi.
  1660. - Add a function of quick cleaning with keyboard (Shift + Alt + X), find in the script code to custom: `e.key === 'X'`.
  1661.  
  1662. v0.6.2.2 2023.05.22
  1663. - Regex checking (when add custom param) optimisation (allow using `[]` in parameter).
  1664.  
  1665. v0.6.2.1 2023.05.22
  1666. - Script language optimisation.
  1667.  
  1668. v0.6.2 2023.05.22
  1669. - Script logic and performance optimisation.
  1670. - Add format validation before adding params (from GM_setValue to storage);
  1671. - Add a script menu function which can remove a custom added parameter.
  1672. - Remove more tracking params.
  1673. - Remove Baidu Search ad results (Testing).
  1674.  
  1675. v0.6.1 2023.05.18
  1676. - Fix an error about array merging, from Array.push() to Array.concat().
  1677. - Clean more params for common sites and `Amazon`, `weibo|stackoverflow|tmall.com`.
  1678. - Reconstruct the functions of history (bind urlchange event to pushState and replaceState).
  1679. - Custom cleaning for `Amazon`.
  1680. - Added a submenu to support adding custom params for current site (host).
  1681.  
  1682. v0.6.0 2023.05.15
  1683. - Clean more parameters for `(douban|imdb|vk|weibo|163|126|baidu.com)|yeah.net`.
  1684. - Resote some parameters for `xda-developers.com`.
  1685. - Add a function of copy cleaning precise time on the video pages of `bilibili`.
  1686. - Clean up copy link behavior on context menu.
  1687. - Script code and regexps matching optimisation, fix several bugs.
  1688.  
  1689. v0.5.8 2023.05.10
  1690. - Fix an issue where the script submenu on github.com was not displayed successfully.
  1691. - Clean copy texts when share video on the video page of bilibili.
  1692. - Clean more parameters for `douyin|tiktok|zhihu|douban|twitter|xda-developers|baidu|cctv.com`.
  1693. - Block signin popups once when enter the pages of zhihu.com.
  1694. - Remove more params for `hoyolab|hoyoverse|mihoyo|miyoushe|miyougift.com` with futnion-commonClean.
  1695. - Timeuout logic optimisation.
  1696.  
  1697. v0.5.7 2023.05.05
  1698. - Optiomise the monitoring of certain events.
  1699. - Remove more parameters for `github|medium|xda-developers|youku.(com)`.
  1700. - Bug fixes.
  1701.  
  1702. v0.5.6 2023.04.28
  1703. - Restore a necessary parameter for baidu.com.
  1704.  
  1705. v0.5.5 2023.04.28
  1706. - Restore normall events within the bili-live player under right-menu clicking.
  1707. - Fixed some coding errors and bug fixes.
  1708. - Update script icon.
  1709. - Add more tracking parameters.
  1710. - Several optimisations, improve cleaning speed.
  1711.  
  1712. v0.5.2 2023.04.20
  1713. - Update site params (add, remove) (Duplicate or necessary parameters for certain sites).
  1714. - Add a condition before bind a event-listenser to button tags.
  1715. - Manually cleaning: Add a script menu on tampermonkey's drop-down menu during default situations.
  1716. - Fixed a problem that clicking to switch page number was invalid (Add label attribute url verificaiton).
  1717. - Code reduction.
  1718.  
  1719. v0.5.1 2023.04.15
  1720. - Fix some bugs where block clicking-events on empty `<a>` link
  1721. - Update excludes pages.
  1722. - Clean some tracking links under space.bilibili.com after click expand more games.
  1723. - Clean `<a>` links with `data-url` as its target url instead of `href`.
  1724. - Clean the params at embedded youtube videos.
  1725.  
  1726. v0.5.0 2023.04.09
  1727. - Added tmall.hk.
  1728. - Added common cleaning to support all websites.
  1729. - Now this script can clean common contents for all sites and specific cleaning for certain sites.
  1730. - Performance optimisation.
  1731.  
  1732. v0.4.10 2023.04.04
  1733. - Added 1688.com.
  1734. - Script operating improvements.
  1735.  
  1736. v0.4.9 2023.04.03
  1737. - Clean Ali sites URLs and block tracking events.
  1738. - alibaba.com
  1739. - alibabagroup.com
  1740. - aliyun.com
  1741. - aliexpress.com
  1742. - alimama.com
  1743. - taobao.com
  1744. - tmall.com
  1745. - youku.com
  1746. - Minor bug fixes.
  1747.  
  1748. v0.4.8-2023.03.25
  1749. - Script optimisation.
  1750. - Minor bug fixes.
  1751.  
  1752. v0.4.7-2023.03.14
  1753. - Clean Youku URLs. [Youku.com].(Testing)
  1754. - Code reduction.
  1755. - Performance optimisation and bug fixes.
  1756.  
  1757. v0.4.6-2023.03.11
  1758. - Clean more baidu links. [Baidu]
  1759. - Clean CSDN URLs. [csdn.net]
  1760. - Script optimisation and bug fixes.
  1761. - Code reduction.
  1762.  
  1763. v0.4.5 2023.03.09
  1764. - Clean more URL under Baidu.com, replace search URL state. [Baidu]
  1765. - Script optimisation and bug fixes. [bilibili]
  1766. - Code reduction.
  1767.  
  1768. v0.4.4 2023.03.05
  1769. - Restore history state at live.bilibili.com. [Bilibili]
  1770. - Clean Bilibili Manga & Show links. [manga/show.bilibili.com]
  1771. - Clean redundant params at douyin.com search page. [Douyin]
  1772. - Code reduction.
  1773.  
  1774. v0.4.3.1 2023.03.01
  1775. - Clean more links at live.bilibili.com. [Bilibili]
  1776. - Script optimisation.
  1777.  
  1778. v0.4.3 2023.02.24
  1779. - Block more tracking events. [Bilibili]
  1780. - Clean more links.[Bilibili]
  1781. - Restore link jump events at comment area. [Bilibili]
  1782. - Script optimisation. [Bilibili]
  1783.  
  1784. v0.4.2.1 2023.02.22
  1785. - Restore `<a>` link click-events on precise time jump at comment area.[www.bilibili.com/video]
  1786.  
  1787. v0.4.2 2023.02.07
  1788. - Optimised events at the search-input-block. [Bilibili]
  1789. - Bug fixes. [search.bilibili.com, www.bilibili.com]
  1790.  
  1791. v0.4.1.2 2023.01.28
  1792. - Bug fixes and performance optimisation. [Bilibili]
  1793.  
  1794. v0.4.1.1 2023.01.25
  1795. - Expanded the effective pages of the script. [Bilibili]
  1796.  
  1797. v0.4.1.0 2023.01.23
  1798. - Performance optimisation and bug fixes.
  1799. - Code reduction.
  1800.  
  1801. v0.4.0.1 2023.01.21
  1802. - Clean other untracked links. [space.bilibili.com]
  1803. - Several bugs fixes. [bilibili.com]
  1804.  
  1805. v0.4.0 2023.01.20
  1806. - Clean Bilibili Video page collections clicking event URL state changes. [www.bilibili.com/video/]
  1807. - Clean Bilibili Search tracking events. [search.bilibili.com]
  1808. - Clean other tracking events (top-menu clicking). [Bilibili]
  1809.  
  1810. v0.3.8.3 2023.01.20
  1811. - Fixed tracking event after video sorting navigation bar items clicked. [space.bilibili.com]
  1812.  
  1813. v0.3.8.2 2023.01.19
  1814. - Fixed navibar items click events [www.bilibili.com/v/popular].
  1815.  
  1816. v0.3.8.1 2023.01.13
  1817. - Clean more links of Baidu.com
  1818.  
  1819. v0.3.8 2023.01.06
  1820. - Block Card-Ads for Bilibili. (And now blocked banner-ads & card-ads for Bilibili)
  1821. - Block [Lucky Draw (The Selection)] popup at [live.bilibili.com]. Disabled by default.
  1822. - (SET [{BlockLivePopups} = true] to enable it.)
  1823. - The script may add menus to unlock custom setting.
  1824.  
  1825. v0.3.7.1 2023.01.02
  1826. - Fixed [space.bilibili.com] effects after paged, navi-bar clicked or menu-item clicked.
  1827. - Added support to clean tracking url at [search.bilibili.com].
  1828.  
  1829. v0.3.7 2023-01-02
  1830. - Naming optimisation.
  1831. - Script handling optimisation. (Bilibili)
  1832. - Added support to block part of Bilibili Ads.
  1833.  
  1834. v0.3.6 2022.12.28
  1835. - Optimise Baidu related search URL, paging URL processing method.
  1836.  
  1837. v0.3.5 2022.12.27
  1838. - Script logic optimisation.
  1839.  
  1840. v0.3.4 2022.12.23
  1841. - Code optimisation. Fixed script's effect range. [Bilibili]
  1842.  
  1843. v0.3.3 2022.12.23
  1844. - Added site support:Clean Baidu <Related Search> URLs.
  1845. - Script optimisations. [space.bilibili.com]
  1846.  
  1847. v0.3.2 2022.12.22
  1848. - Restore pushstate session (address bar url display, replace history). [Bilibili]
  1849. - Minor optimisations. [Bilibili]
  1850.  
  1851. v0.3.1 2022.12.22
  1852. - Optimized the effective range. [Bilibili]
  1853.  
  1854. v0.3 2022.12.22
  1855. - Added Bilibili Home page, Popular/Rank page, now it can takeeffect on most pages. [Bilibili]
  1856.  
  1857. v0.2 2022.12.21
  1858. - Added missing tags. [Bilibili]
  1859.  
  1860. v0.1 2022.12.20
  1861. - Initial release.
  1862. */