A lot of QOL changement, remove Zen, config Qutebrowser, update a lot of things

Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
This commit is contained in:
Hadi
2026-04-18 00:44:22 +02:00
parent 241db5ce7a
commit 9e24c44c53
49 changed files with 4559 additions and 1777 deletions
@@ -0,0 +1,826 @@
// ==UserScript==
// @name Don't track me Google
// @namespace Rob W
// @description Removes the annoying link-conversion at Google Search/maps/...
// @version 4.28
// @icon https://raw.githubusercontent.com/Rob--W/dont-track-me-google/master/icon48.png
// @supportURL https://github.com/Rob--W/dont-track-me-google/issues
// @license MIT
// @run-at document-start
// @match *://*.google.com/*
// @match *://*.google.ad/*
// @match *://*.google.ae/*
// @match *://*.google.com.af/*
// @match *://*.google.com.ag/*
// @match *://*.google.com.ai/*
// @match *://*.google.al/*
// @match *://*.google.am/*
// @match *://*.google.co.ao/*
// @match *://*.google.com.ar/*
// @match *://*.google.as/*
// @match *://*.google.at/*
// @match *://*.google.com.au/*
// @match *://*.google.az/*
// @match *://*.google.ba/*
// @match *://*.google.com.bd/*
// @match *://*.google.be/*
// @match *://*.google.bf/*
// @match *://*.google.bg/*
// @match *://*.google.com.bh/*
// @match *://*.google.bi/*
// @match *://*.google.bj/*
// @match *://*.google.com.bn/*
// @match *://*.google.com.bo/*
// @match *://*.google.com.br/*
// @match *://*.google.bs/*
// @match *://*.google.bt/*
// @match *://*.google.co.bw/*
// @match *://*.google.by/*
// @match *://*.google.com.bz/*
// @match *://*.google.ca/*
// @match *://*.google.cd/*
// @match *://*.google.cf/*
// @match *://*.google.cg/*
// @match *://*.google.ch/*
// @match *://*.google.ci/*
// @match *://*.google.co.ck/*
// @match *://*.google.cl/*
// @match *://*.google.cm/*
// @match *://*.google.cn/*
// @match *://*.google.com.co/*
// @match *://*.google.co.cr/*
// @match *://*.google.com.cu/*
// @match *://*.google.cv/*
// @match *://*.google.com.cy/*
// @match *://*.google.cz/*
// @match *://*.google.de/*
// @match *://*.google.dj/*
// @match *://*.google.dk/*
// @match *://*.google.dm/*
// @match *://*.google.com.do/*
// @match *://*.google.dz/*
// @match *://*.google.com.ec/*
// @match *://*.google.ee/*
// @match *://*.google.com.eg/*
// @match *://*.google.es/*
// @match *://*.google.com.et/*
// @match *://*.google.fi/*
// @match *://*.google.com.fj/*
// @match *://*.google.fm/*
// @match *://*.google.fr/*
// @match *://*.google.ga/*
// @match *://*.google.ge/*
// @match *://*.google.gg/*
// @match *://*.google.com.gh/*
// @match *://*.google.com.gi/*
// @match *://*.google.gl/*
// @match *://*.google.gm/*
// @match *://*.google.gp/*
// @match *://*.google.gr/*
// @match *://*.google.com.gt/*
// @match *://*.google.gy/*
// @match *://*.google.com.hk/*
// @match *://*.google.hn/*
// @match *://*.google.hr/*
// @match *://*.google.ht/*
// @match *://*.google.hu/*
// @match *://*.google.co.id/*
// @match *://*.google.ie/*
// @match *://*.google.co.il/*
// @match *://*.google.im/*
// @match *://*.google.co.in/*
// @match *://*.google.iq/*
// @match *://*.google.is/*
// @match *://*.google.it/*
// @match *://*.google.je/*
// @match *://*.google.com.jm/*
// @match *://*.google.jo/*
// @match *://*.google.co.jp/*
// @match *://*.google.co.ke/*
// @match *://*.google.com.kh/*
// @match *://*.google.ki/*
// @match *://*.google.kg/*
// @match *://*.google.co.kr/*
// @match *://*.google.com.kw/*
// @match *://*.google.kz/*
// @match *://*.google.la/*
// @match *://*.google.com.lb/*
// @match *://*.google.li/*
// @match *://*.google.lk/*
// @match *://*.google.co.ls/*
// @match *://*.google.lt/*
// @match *://*.google.lu/*
// @match *://*.google.lv/*
// @match *://*.google.com.ly/*
// @match *://*.google.co.ma/*
// @match *://*.google.md/*
// @match *://*.google.me/*
// @match *://*.google.mg/*
// @match *://*.google.mk/*
// @match *://*.google.ml/*
// @match *://*.google.com.mm/*
// @match *://*.google.mn/*
// @match *://*.google.ms/*
// @match *://*.google.com.mt/*
// @match *://*.google.mu/*
// @match *://*.google.mv/*
// @match *://*.google.mw/*
// @match *://*.google.com.mx/*
// @match *://*.google.com.my/*
// @match *://*.google.co.mz/*
// @match *://*.google.com.na/*
// @match *://*.google.com.nf/*
// @match *://*.google.com.ng/*
// @match *://*.google.com.ni/*
// @match *://*.google.ne/*
// @match *://*.google.nl/*
// @match *://*.google.no/*
// @match *://*.google.com.np/*
// @match *://*.google.nr/*
// @match *://*.google.nu/*
// @match *://*.google.co.nz/*
// @match *://*.google.com.om/*
// @match *://*.google.com.pa/*
// @match *://*.google.com.pe/*
// @match *://*.google.com.pg/*
// @match *://*.google.com.ph/*
// @match *://*.google.com.pk/*
// @match *://*.google.pl/*
// @match *://*.google.pn/*
// @match *://*.google.com.pr/*
// @match *://*.google.ps/*
// @match *://*.google.pt/*
// @match *://*.google.com.py/*
// @match *://*.google.com.qa/*
// @match *://*.google.ro/*
// @match *://*.google.ru/*
// @match *://*.google.rw/*
// @match *://*.google.com.sa/*
// @match *://*.google.com.sb/*
// @match *://*.google.sc/*
// @match *://*.google.se/*
// @match *://*.google.com.sg/*
// @match *://*.google.sh/*
// @match *://*.google.si/*
// @match *://*.google.sk/*
// @match *://*.google.com.sl/*
// @match *://*.google.sn/*
// @match *://*.google.so/*
// @match *://*.google.sm/*
// @match *://*.google.sr/*
// @match *://*.google.st/*
// @match *://*.google.com.sv/*
// @match *://*.google.td/*
// @match *://*.google.tg/*
// @match *://*.google.co.th/*
// @match *://*.google.com.tj/*
// @match *://*.google.tk/*
// @match *://*.google.tl/*
// @match *://*.google.tm/*
// @match *://*.google.tn/*
// @match *://*.google.to/*
// @match *://*.google.com.tr/*
// @match *://*.google.tt/*
// @match *://*.google.com.tw/*
// @match *://*.google.co.tz/*
// @match *://*.google.com.ua/*
// @match *://*.google.co.ug/*
// @match *://*.google.co.uk/*
// @match *://*.google.com.uy/*
// @match *://*.google.co.uz/*
// @match *://*.google.com.vc/*
// @match *://*.google.co.ve/*
// @match *://*.google.vg/*
// @match *://*.google.co.vi/*
// @match *://*.google.com.vn/*
// @match *://*.google.vu/*
// @match *://*.google.ws/*
// @match *://*.google.rs/*
// @match *://*.google.co.za/*
// @match *://*.google.co.zm/*
// @match *://*.google.co.zw/*
// @match *://*.google.cat/*
// @match *://*.google.ng/*
// @downloadURL https://update.greasyfork.org/scripts/428243/Don%27t%20track%20me%20Google.user.js
// @updateURL https://update.greasyfork.org/scripts/428243/Don%27t%20track%20me%20Google.meta.js
// ==/UserScript==
document.addEventListener('mousedown', handlePointerPress, true);
document.addEventListener('touchstart', handlePointerPress, true);
document.addEventListener('click', handleClick, true);
var scriptCspNonce;
var needsCspNonce = typeof browser !== 'undefined'; // Firefox.
var preferenceObservers = [];
setupAggresiveUglyLinkPreventer();
var forceNoReferrer = true;
var noping = true;
if (typeof chrome == 'object' && chrome.storage) {
(chrome.storage.sync || chrome.storage.local).get({
forceNoReferrer: true,
// From version 4.7 until 4.11, the preference was the literal value of
// the referrer policy.
referrerPolicy: 'no-referrer',
noping: true,
}, function(items) {
if (items) {
// Migration code (to be removed in the future).
if (items.referrerPolicy === '') {
// User explicitly allowed referrers to be sent, respect that.
items.forceNoReferrer = false;
}
forceNoReferrer = items.forceNoReferrer;
noping = items.noping;
callPreferenceObservers();
}
});
chrome.storage.onChanged.addListener(function(changes) {
if (changes.forceNoReferrer) {
forceNoReferrer = changes.forceNoReferrer.newValue;
}
if (changes.noping) {
noping = changes.noping.newValue;
}
callPreferenceObservers();
});
}
function callImmediatelyAndOnPreferenceUpdate(callback) {
callback();
preferenceObservers.push(callback);
}
function callPreferenceObservers() {
// This method is usually once, and occasionally more than once if the user
// changes a preference. For simplicity we don't check whether a pref was
// changed before calling a callback - these are cheap anyway.
preferenceObservers.forEach(function(callback) {
callback();
});
}
function getReferrerPolicy() {
return forceNoReferrer ? 'origin' : '';
}
function updateReferrerPolicy(a) {
if (a.referrerPolicy === 'no-referrer') {
// "no-referrer" is more privacy-friendly than "origin".
return;
}
var referrerPolicy = getReferrerPolicy();
if (referrerPolicy) {
a.referrerPolicy = referrerPolicy;
}
}
function handlePointerPress(e) {
var a = e.target;
while (a && !a.href) {
a = a.parentElement;
}
if (!a) {
return;
}
var inlineMousedown = a.getAttribute('onmousedown');
// return rwt(....); // E.g Google search results.
// return google.rwt(...); // E.g. sponsored search results
// return google.arwt(this); // E.g. sponsored search results (dec 2016).
if (inlineMousedown && /\ba?rwt\(/.test(inlineMousedown)) {
a.removeAttribute('onmousedown');
// Just in case:
a.removeAttribute('ping');
// In Chrome, removing onmousedown during event dispatch does not
// prevent the inline listener from running... So we have to cancel
// event propagation just in case.
e.stopImmediatePropagation();
}
if (noping) {
a.removeAttribute('ping');
}
var realLink = getRealLinkFromGoogleUrl(a);
if (realLink) {
a.href = realLink;
// Sometimes, two fixups are needed, on old mobile user agents:
// /url?q=https://googleweblight.com/fp?u=... -> ...
realLink = getRealLinkFromGoogleUrl(a);
if (realLink) {
a.href = realLink;
}
}
updateReferrerPolicy(a);
if (e.eventPhase === Event.CAPTURING_PHASE) {
// Our event listener runs first, to sanitize the link.
// But the page may have an event handler that modifies the link again.
// We can append a listener to the bubbling phase of the (current)
// event dispatch to fix the link up again, provided that the page did
// not call stopPropagation() or stopImmediatePropagation().
var eventOptions = { capture: false, once: true };
a.addEventListener(e.type, handlePointerPress, eventOptions);
document.addEventListener(e.type, handlePointerPress, eventOptions);
}
}
// This is specifically designed for catching clicks in Gmail.
// Gmail binds a click handler to a <div> and cancels the event after opening
// a window with an ugly URL. It uses a blank window + meta refresh in Firefox,
// which is too crazy to patch. So we just make sure that the browser's default
// click handler is activated (=open link in new tab).
// The entry point for this crazy stuff is shown in my comment at
// https://github.com/Rob--W/dont-track-me-google/issues/2
function handleClick(e) {
if (e.button !== 0) {
return;
}
var a = e.target;
while (a && !a.href) {
a = a.parentElement;
}
if (!a) {
return;
}
if (a.dataset && a.dataset.url) {
var realLink = getSanitizedIntentUrl(a.dataset.url);
if (realLink) {
a.dataset.url = realLink;
}
}
if (!location.hostname.startsWith('mail.')) {
// This hack was designed for Gmail, but broke other Google sites:
// - https://github.com/Rob--W/dont-track-me-google/issues/6
// - https://github.com/Rob--W/dont-track-me-google/issues/19
// So let's disable it for every domain except Gmail.
return;
}
// TODO: Consider using a.baseURI instead of location in case Gmail ever
// starts using <base href>?
if (a.origin === location.origin) {
// Same-origin link.
// E.g. an in-page navigation at Google Docs (#...)
// or an attachment at Gmail (https://mail.google.com/mail/u/0?ui=2&...)
return;
}
if (a.protocol !== 'http:' &&
a.protocol !== 'https:' &&
a.protocol !== 'ftp:') {
// Be conservative and don't block too much. E.g. Gmail has special
// handling for mailto:-URLs, and using stopPropagation now would
// cause mailto:-links to be opened by the platform's default mailto
// handler instead of Gmail's handler (=open in new window).
return;
}
if (a.target === '_blank') {
e.stopPropagation();
updateReferrerPolicy(a);
}
}
/**
* @param {URL|HTMLHyperlinkElementUtils} a
* @returns {String} the real URL if the given link is a Google redirect URL.
*/
function getRealLinkFromGoogleUrl(a) {
if (a.protocol !== 'https:' && a.protocol !== 'http:') {
return;
}
var url;
if ((a.hostname === location.hostname || a.hostname === 'www.google.com') &&
(a.pathname === '/url' || a.pathname === '/local_url' ||
a.pathname === '/searchurl/rr.html' ||
a.pathname === '/linkredirect')) {
// Google Maps / Dito (/local_url?q=<url>)
// Mobile (/url?q=<url>)
// Google Meet's chat (/linkredirect?authuser=0&dest=<url>)
url = /[?&](?:q|url|dest)=((?:https?|ftp)[%:][^&]+)/.exec(a.search);
if (url) {
return decodeURIComponent(url[1]);
}
// Help pages, e.g. safe browsing (/url?...&q=%2Fsupport%2Fanswer...)
url = /[?&](?:q|url)=((?:%2[Ff]|\/)[^&]+)/.exec(a.search);
if (url) {
return a.origin + decodeURIComponent(url[1]);
}
// Redirect pages for Android intents (/searchurl/rr.html#...&url=...)
// rr.html only supports http(s). So restrict to http(s) only.
url = /[#&]url=(https?[:%][^&]+)/.exec(a.hash);
if (url) {
return decodeURIComponent(url[1]);
}
}
// Google Search with old mobile UA (e.g. Firefox 41).
if (a.hostname === 'googleweblight.com' && a.pathname === '/fp') {
url = /[?&]u=((?:https?|ftp)[%:][^&]+)/.exec(a.search);
if (url) {
return decodeURIComponent(url[1]);
}
}
}
/**
* @param {string} intentUrl
* @returns {string|undefined} The sanitized intent:-URL if it was an intent URL
* with embedded tracking link.
*/
function getSanitizedIntentUrl(intentUrl) {
if (!intentUrl.startsWith('intent:')) {
return;
}
// https://developer.chrome.com/multidevice/android/intents#syntax
var BROWSER_FALLBACK_URL = ';S.browser_fallback_url=';
var indexStart = intentUrl.indexOf(BROWSER_FALLBACK_URL);
if (indexStart === -1) {
return;
}
indexStart += BROWSER_FALLBACK_URL.length;
var indexEnd = intentUrl.indexOf(';', indexStart);
indexEnd = indexEnd === -1 ? intentUrl.length : indexEnd;
var url = decodeURIComponent(intentUrl.substring(indexStart, indexEnd));
var realUrl = getRealLinkFromGoogleUrl(newURL(url));
if (!realUrl) {
return;
}
return intentUrl.substring(0, indexStart) +
encodeURIComponent(realUrl) +
intentUrl.substring(indexEnd);
}
/**
* Intercept the .href setter in the page so that the page can never change the
* URL to a tracking URL. Just intercepting mousedown/touchstart is not enough
* because e.g. on Google Maps, the page rewrites the URL in the contextmenu
* event at the bubbling event stage and then stops the event propagation. So
* there is no event-driven way to fix the URL. The DOMAttrModified event could
* be used, but the event is deprecated, so not a viable long-term solution.
*/
function setupAggresiveUglyLinkPreventer() {
// This content script runs as document_start, so we can have some assurance
// that the methods in the page are reliable.
var s = document.createElement('script');
if (getScriptCspNonce()) {
s.setAttribute('nonce', scriptCspNonce);
} else if (document.readyState !== 'complete' && needsCspNonce) {
// In Firefox, a page's CSP is enforced for content scripts, so we need
// to wait for the document to be loaded (we may be at document_start)
// and find a fitting CSP nonce.
findScriptCspNonce(setupAggresiveUglyLinkPreventer);
return;
}
s.textContent = '(' + function(getRealLinkFromGoogleUrl) {
var proto = HTMLAnchorElement.prototype;
// The link target can be changed in many ways, but let's only consider
// the .href attribute since it's probably the only used setter.
var hrefProp = Object.getOwnPropertyDescriptor(proto, 'href');
var hrefGet = Function.prototype.call.bind(hrefProp.get);
var hrefSet = Function.prototype.call.bind(hrefProp.set);
Object.defineProperty(proto, 'href', {
configurable: true,
enumerable: true,
get() {
return hrefGet(this);
},
set(v) {
hrefSet(this, v);
try {
v = getRealLinkFromGoogleUrl(this);
if (v) {
hrefSet(this, v);
}
} catch (e) {
// Not expected to happen, but don't break the setter if for
// some reason the (hostile) page broke the link APIs.
}
updateReferrerPolicy(this);
},
});
function replaceAMethod(methodName, methodFunc) {
// Overwrite the methods without triggering setters, because that
// may inadvertently overwrite the prototype, as observed in
// https://github.com/Rob--W/dont-track-me-google/issues/52#issuecomment-1596207655
Object.defineProperty(proto, methodName, {
configurable: true,
// All methods that we are overriding are not part of
// HTMLAnchorElement.prototype, but inherit.
enumerable: false,
writable: true,
value: methodFunc,
});
}
// proto inherits Element.prototype.setAttribute:
var setAttribute = Function.prototype.call.bind(proto.setAttribute);
replaceAMethod('setAttribute', function(name, value) {
// Attribute names are not case-sensitive, but weird capitalizations
// are unlikely, so only check all-lowercase and all-uppercase.
if (name === 'href' || name === 'HREF') {
this.href = value;
} else {
setAttribute(this, name, value);
}
});
// proto inherits EventTarget.prototype.dispatchEvent:
var aDispatchEvent = Function.prototype.apply.bind(proto.dispatchEvent);
replaceAMethod('dispatchEvent', function() {
updateReferrerPolicy(this);
return aDispatchEvent(this, arguments);
});
// proto inherits HTMLElement.prototype.click:
var aClick = Function.prototype.apply.bind(proto.click);
replaceAMethod('click', function() {
updateReferrerPolicy(this);
return aClick(this, arguments);
});
var rpProp = Object.getOwnPropertyDescriptor(proto, 'referrerPolicy');
var rpGet = Function.prototype.call.bind(rpProp.get);
var rpSet = Function.prototype.call.bind(rpProp.set);
var currentScript = document.currentScript;
var getReferrerPolicy = Object.getOwnPropertyDescriptor(
HTMLScriptElement.prototype,
'referrerPolicy'
).get.bind(currentScript);
function updateReferrerPolicy(a) {
try {
if (rpGet(a) === 'no-referrer') {
// "no-referrer" is more privacy-friendly than "origin".
return;
}
var referrerPolicy = getReferrerPolicy();
if (referrerPolicy) {
rpSet(a, referrerPolicy);
}
} catch (e) {
// Not expected to happen, but don't break callers if it happens
// anyway.
}
}
currentScript.dataset.jsEnabled = 1;
} + ')(' + getRealLinkFromGoogleUrl + ');';
callImmediatelyAndOnPreferenceUpdate(function forceNoReferrerChanged() {
// Send the desired referrerPolicy value to the injected script.
s.referrerPolicy = getReferrerPolicy();
});
(document.head || document.documentElement).appendChild(s);
s.remove();
if (!s.dataset.jsEnabled) {
cleanLinksWhenJsIsDisabled();
if (!needsCspNonce) {
needsCspNonce = true;
// This is not Firefox, but the script was blocked. Perhaps a CSP
// nonce is needed anyway.
findScriptCspNonce(function() {
if (scriptCspNonce) {
setupAggresiveUglyLinkPreventer();
}
});
}
} else {
// Scripts enabled (not blocked by CSP), run other inline scripts.
blockTrackingBeacons();
overwriteWindowOpen();
if (location.hostname === 'docs.google.com') {
// Google Docs have simple non-JS interfaces where the ugly links
// are hard-coded in the HTML. Remove them (#51).
// https://docs.google.com/document/d/.../mobilebasic
// https://docs.google.com/spreadsheets/d/.../htmlview
cleanLinksWhenJsIsDisabled();
}
}
}
// Block sendBeacon requests with destination /gen_204, because Google
// asynchronously sends beacon requests in response to mouse events on links:
// https://github.com/Rob--W/dont-track-me-google/issues/20
//
// This implementation also blocks other forms of tracking via gen_204 as a side
// effect. That is not fully intentional, but given the lack of obvious ways to
// discern such link-tracking events from others, I will block all of them.
function blockTrackingBeacons() {
var s = document.createElement('script');
if (getScriptCspNonce()) {
s.setAttribute('nonce', scriptCspNonce);
}
s.textContent = '(' + function() {
var navProto = window.Navigator.prototype;
var navProtoSendBeacon = navProto.sendBeacon;
if (!navProtoSendBeacon) {
return;
}
var sendBeacon = Function.prototype.apply.bind(navProtoSendBeacon);
// Blocks the following:
// gen_204
// /gen_204
// https://www.google.com/gen_204
var isTrackingUrl = RegExp.prototype.test.bind(
/^(?:(?:https?:\/\/[^\/]+)?\/)?gen_204(?:[?#]|$)/);
navProto.sendBeacon = function(url, data) {
if (isTrackingUrl(url) && isNoPingEnabled()) {
// Lie that the data has been transmitted to avoid fallbacks.
return true;
}
return sendBeacon(this, arguments);
};
var currentScript = document.currentScript;
var getElementId = Object.getOwnPropertyDescriptor(
Element.prototype,
'id'
).get.bind(currentScript);
function isNoPingEnabled() {
try {
return getElementId() !== '_dtmg_do_not_touch_ping';
} catch (e) {
return true;
}
}
} + ')();';
callImmediatelyAndOnPreferenceUpdate(function nopingChanged() {
// Send the noping value to the injected script. The "id" property is
// mirrored and can have an arbitrary (string) value, so we use that:
s.id = noping ? '' : '_dtmg_do_not_touch_ping';
});
(document.head || document.documentElement).appendChild(s);
s.remove();
}
// Google sometimes uses window.open() to open ugly links.
// https://github.com/Rob--W/dont-track-me-google/issues/18
// https://github.com/Rob--W/dont-track-me-google/issues/41
function overwriteWindowOpen() {
var s = document.createElement('script');
if (getScriptCspNonce()) {
s.setAttribute('nonce', scriptCspNonce);
}
s.textContent = '(' + function() {
var open = window.open;
window.open = function(url, windowName, windowFeatures) {
var isBlankUrl = !url || url === "about:blank";
try {
if (!isBlankUrl) {
var a = document.createElement('a');
// Triggers getRealLinkFromGoogleUrl via the href setter in
// setupAggresiveUglyLinkPreventer.
a.href = url;
url = a.href;
// The origin check exists to avoid adding "noreferrer" to
// same-origin popups. That implies noopener and causes
// https://github.com/Rob--W/dont-track-me-google/issues/43
// And allow any Google domain to support auth popups:
// https://github.com/Rob--W/dont-track-me-google/issues/45
// And don't bother editing the list if it already contains
// "opener" (it would be disabled by "noreferrer").
if (a.referrerPolicy && a.origin !== location.origin &&
!/\.google\.([a-z]+)$/.test(a.hostname) &&
!/\bopener|noreferrer/.test(windowFeatures)) {
if (windowFeatures) {
windowFeatures += ',';
} else {
windowFeatures = '';
}
windowFeatures += 'noreferrer';
}
}
} catch (e) {
// Not expected to happen, but don't break callers if it does.
}
var win = open(url, windowName, windowFeatures);
try {
if (isBlankUrl && win) {
// In Google Docs, sometimes a blank document is opened,
// and document.write is used to insert a redirector.
// https://github.com/Rob--W/dont-track-me-google/issues/41
var doc = win.document;
var docWrite = win.Function.prototype.call.bind(doc.write);
doc.write = function(markup) {
try {
markup = fixupDocMarkup(markup);
} catch (e) {
// Not expected, but don't break callers otherwise.
}
return docWrite(this, markup);
};
}
} catch (e) {
// Not expected to happen, but don't break callers if it does.
}
return win;
};
function fixupDocMarkup(html) {
html = html || '';
html += '';
return html.replace(
/<meta [^>]*http-equiv=(["']?)refresh\1[^>]*>/i,
function(m) {
var doc = new DOMParser().parseFromString(m, 'text/html');
var meta = doc.querySelector('meta[http-equiv=refresh]');
return meta && fixupMetaUrl(meta) || m;
});
}
function fixupMetaUrl(meta) {
var parts = /^(\d*;\s*url=)(.+)$/i.exec(meta.content);
if (!parts) {
return;
}
var metaPrefix = parts[1];
var url = parts[2];
var a = document.createElement('a');
// Triggers getRealLinkFromGoogleUrl via the href setter in
// setupAggresiveUglyLinkPreventer.
a.href = url;
url = a.href;
meta.content = metaPrefix + url;
var html = meta.outerHTML;
if (a.referrerPolicy) {
// Google appears to already append the no-referrer
// meta tag, but add one just in case it doesn't.
html = '<meta name="referrer" content="no-referrer">' + html;
}
return html;
}
} + ')();';
(document.head || document.documentElement).appendChild(s);
s.remove();
}
function cleanLinksWhenJsIsDisabled() {
// When JavaScript is disabled, Google sets the "href" attribute's value to
// an ugly URL. Although the link is rewritten on click, we still need to
// rewrite the link even earlier because otherwise the ugly URL is shown in
// the tooltip upon hover.
if (document.readyState == 'complete') {
cleanAllLinks();
return;
}
// When JS is disabled, the links won't change after the document finishes
// loading. Until the DOM has finished loading, use the mouseover event to
// beautify links (the DOMContentLoaded may be delayed on slow networks).
document.addEventListener('mouseover', handleMouseOver);
document.addEventListener('DOMContentLoaded', function() {
document.removeEventListener('mouseover', handleMouseOver);
cleanAllLinks();
}, {once: true});
function cleanAllLinks() {
var as = document.querySelectorAll('a[href]');
for (var i = 0; i < as.length; ++i) {
var href = getRealLinkFromGoogleUrl(as[i]);
if (href) {
as[i].href = href;
}
}
}
function handleMouseOver(e) {
var a = e.target;
var href = a.href && getRealLinkFromGoogleUrl(a);
if (href) {
a.href = href;
}
}
}
function getScriptCspNonce() {
var scripts = document.querySelectorAll('script[nonce]');
for (var i = 0; i < scripts.length && !scriptCspNonce; ++i) {
scriptCspNonce = scripts[i].nonce;
}
return scriptCspNonce;
}
function findScriptCspNonce(callback) {
var timer;
function checkDOM() {
if (getScriptCspNonce() || document.readyState === 'complete') {
document.removeEventListener('DOMContentLoaded', checkDOM, true);
if (timer) {
clearTimeout(timer);
}
callback();
return;
}
timer = setTimeout(checkDOM, 50);
}
document.addEventListener('DOMContentLoaded', checkDOM, true);
checkDOM();
}
function newURL(href) {
try {
return new URL(href);
} catch (e) {
var a = document.createElement('a');
a.href = href;
return a;
}
}
@@ -0,0 +1,984 @@
// ==UserScript==
// @name I don't care about cookies
// @name:vi Tôi không quan tâm về cookie
// @name:zh-CN 我不关心cookie
// @name:zh-TW 我不關心cookie
// @name:ja クッキーについては気にしない
// @name:ru Я не забочусь о куки
// @namespace http://tampermonkey.net/
// @version 2025.01.03.2
// @description Remove cookie warnings from almost all websites! Auto accept cookies and remove annoying cookie popups
// @description:vi Loại bỏ cảnh báo cookie từ hầu hết các trang web! Tự động chấp nhận cookie và xóa các popup cookie phiền phức
// @description:zh-CN 自动接受cookie并移除烦人的cookie弹窗
// @description:zh-TW 自動接受cookie並移除煩人的cookie彈窗
// @description:ru Автоматическое принятие cookie и удаление надоедливых всплывающих окон
// @description:ja 自動承認cookieと迷惑なポップアップを削除
// @author Yuusei
// @match *://*/*
// @grant none
// @icon https://lh3.googleusercontent.com/sCLTYpGX0VcVootQ_XaFQ9saRIhVWu79ngSzY5eTZ5evRpJ_Q27OdvxA4RrOoZXP7Q4enFh-u6VhxObcJLfARw1g=s60
// @compatible chrome
// @compatible edge
// @compatible firefox
// @compatible safari
// @run-at document-start
// @license gpl-3.0-only
// @downloadURL https://update.greasyfork.org/scripts/522645/I%20don%27t%20care%20about%20cookies.user.js
// @updateURL https://update.greasyfork.org/scripts/522645/I%20don%27t%20care%20about%20cookies.meta.js
// ==/UserScript==
(function () {
'use strict';
const CONSENT_TEXTS = {
en: ['accept', 'accept all', 'agree', 'continue', 'got it', 'reject all', 'decline', 'necessary only', 'required only', 'manage', 'customize'],
vi: ['chấp nhận', 'chấp nhận tất cả', 'đồng ý', 'tiếp tục', 'từ chối tất cả', 'từ chối', 'chỉ cần thiết', 'tùy chỉnh', 'quản lý', 'cho phép', 'đồng ý và tiếp tục', 'tôi đồng ý', 'xác nhận', 'tôi chấp nhận', 'đồng ý tất cả', 'chấp nhận và tiếp tục', 'cho phép tất cả'],
zh: ['接受', '接受全部', '同意', '继续', '拒绝全部', '拒绝', '仅必要', '管理', '自定义'],
ru: ['принять', 'принять все', 'согласен', 'продолжить', 'отклонить все', 'отклонить', 'только необходимые', 'настроить', 'управлять'],
ja: ['承認', '同意', '続ける', 'すべて拒否', '拒否', '必要のみ', 'カスタマイズ', '管理'],
de: ['akzeptieren', 'einverstanden', 'fortfahren', 'alle ablehnen', 'ablehnen', 'nur notwendige', 'anpassen', 'verwalten'],
fr: ['accepter', 'accepter tout', 'accepte', 'continuer', 'tout refuser', 'refuser', 'uniquement nécessaire', 'personnaliser', 'gérer'],
es: ['aceptar', 'acepto todo', 'acepto', 'continuar', 'rechazar todo', 'rechazar', 'solo necesario', 'personalizar', 'gestionar'],
it: ['accetta', 'accetto tutto', 'accetto', 'continua', 'rifiuta tutto', 'rifiuta', 'solo necessari', 'personalizza', 'gestisci'],
pl: ['akceptuj', 'akceptuj wszystko', 'zgadzam się', 'kontynuuj', 'odrzuć wszystko', 'odrzuć', 'tylko niezbędne', 'dostosuj', 'zarządzaj'],
nl: ['accepteren', 'accepteren', 'doorgaan', 'alles weigeren', 'weigeren', 'alleen noodzakelijk', 'aanpassen', 'beheren'],
ko: ['동의', '모두 동의', '계속하기', '모두 거부', '거부', '필수만', '설정', '관리'],
th: ['ยอมรับ', 'ยอมรับทั้งหมด', 'ตกลง', 'ปฏิเสธทั้งหมด', 'ปฏิเสธ', 'จำเป็นเท่านั้น', 'ตั้งค่า', 'จัดการ'],
id: ['setuju', 'setuju semua', 'lanjutkan', 'tolak semua', 'tolak', 'wajib saja', 'pengaturan', 'kelola'],
ms: ['terima', 'terima semua', 'teruskan', 'tolak semua', 'tolak', 'perlu sahaja', 'tetapan', 'urus'],
pt: ['aceitar', 'aceitar tudo', 'continuar', 'rejeitar tudo', 'rejeitar', 'necessário', 'configurar', 'gerir'],
sv: ['godkänn', 'godkänn alla', 'fortsätt', 'neka alla', 'neka', 'nödvändiga', 'inställningar', 'hantera'],
da: ['accepter', 'accepter alle', 'fortsæt', 'afvis alle', 'afvis', 'nødvendige', 'indstillinger', 'administrer'],
fi: ['hyväksy', 'hyväksy kaikki', 'jatka', 'hylkää kaikki', 'hylkää', 'välttämätön', 'asetukset', 'hallitse'],
'zh-CN': ['接受', '接受全部', '同意', '继续', '我同意', '确定', '确认', '知道了', '好的', '拒绝全部', '拒绝', '仅必要', '设置', '自定义', '管理', '保存设置', '允许', '允许全部', '接受并继续', '同意并继续', '保存并继续'],
'zh-TW': ['接受', '接受全部', '同意', '繼續', '我同意', '確定', '確認', '知道了', '好的', '拒絕全部', '拒絕', '僅必要', '設置', '自定義', '管理', '保存設置', '允許', '允許全部', '接受並繼續', '同意並繼續', '保存並繼續'],
ko: ['동의', '모두 동의', '수락', '계속하기', '확인', '거부', '거부하기', '필수만', '설정', '관리', '저장', '허용', '모두 허용'],
th: ['ยอมรับ', 'ยอมรับทั้งหมด', 'ตกลง', 'ดำเนินการต่อ', 'ปฏิเสธ', 'ปฏิเสธทั้งหมด', 'จำเป็นเท่านั้น', 'ตั้งค่า', 'จัดการ', 'บันทึก', 'อนุญาต', 'อนุญาตทั้งหมด'],
id: ['terima', 'terima semua', 'setuju', 'lanjutkan', 'tolak', 'tolak semua', 'wajib saja', 'pengaturan', 'kelola', 'simpan', 'izinkan', 'izinkan semua'],
ms: ['terima', 'terima semua', 'setuju', 'teruskan', 'tolak', 'tolak semua', 'perlu sahaja', 'tetapan', 'urus', 'simpan', 'benarkan', 'benarkan semua'],
};
function matchesConsentText(element) {
const text = element.textContent.toLowerCase();
const lang = document.documentElement.lang || 'en';
const texts = CONSENT_TEXTS[lang.split('-')[0]] || CONSENT_TEXTS['en'];
return texts.some(t => text.includes(t));
}
// Utility functions
function _sl(selector, container) {
return (container || document).querySelector(selector);
}
function _id(id) {
return document.getElementById(id);
}
function _ev(selector, container, full) {
return document.evaluate((typeof full == 'undefined' ? '//' : '') + selector, container || document, null, XPathResult.ANY_TYPE, null).iterateNext();
}
function _if(condition, ...selectors) {
return _sl(condition) ? _chain(...selectors) : false;
}
function _if_else(condition, if_selectors, else_selectors) {
if (_sl(condition)) return _chain(...if_selectors);
return _chain(...else_selectors);
}
function _chain(...selectors) {
let elements,
l = selectors.length;
let flagUnique = false,
flagOptional = false,
flagAllMatches = false;
for (let i = currentChainElement; i < l; i++) {
if (/^FLAG\:/.test(selectors[i])) {
selectors[i]
.split(':')[1]
.split(',')
.forEach(function (flag) {
if (flag == 'UNIQUE') flagUnique = true;
else if (flag == 'OPTIONAL') flagOptional = true;
else if (flag == 'REQUIRED') flagOptional = false;
else if (flag == 'ALL-MATCHES') flagAllMatches = true;
else if (flag == 'SINGLE-MATCH') flagAllMatches = false;
});
continue;
}
if (flagUnique) selectors[i] += selectors[i].startsWith('//') ? '[not(contains(@class, "' + classname + '"))]' : ':not(.' + classname + ')';
if (i == l - 1) return selectors[i];
elements = _sl(selectors[i], false, flagAllMatches);
if (!flagAllMatches) elements = elements ? [elements] : [];
if (!elements.length) {
if (flagOptional) {
currentChainElement++;
continue;
}
return false;
}
currentChainElement++;
elements.forEach(function (element) {
if (flagUnique) element.classList.add(classname);
if (element.nodeName == 'OPTION') element.selected = true;
else element.click();
});
}
return false;
}
function getItem(hostname) {
switch (hostname) {
case 'youtube.com':
case 'www.youtube.com':
return { strict: true, key: 'CONSENT', value: 'PENDING+999' };
case 'google.com':
case 'www.google.com':
return { strict: true, key: 'CONSENT', value: 'YES+' };
case 'twitter.com':
case 'www.twitter.com':
return { strict: false, key: 'twtr_cookie_consent', value: '1' };
case 'pepephone.com':
case 'lyricsbox.com':
return { strict: true, key: 'cookieconsent', value: '1111' };
case 'kontaktbazar.at':
case 'hoernews.de':
return { strict: false, key: 'cookieconsent_status', value: 'dismiss' };
case 'vodafoneziggo.nl':
return { strict: false, key: 'cookies-accepted', value: 'true' };
case 'frankfurt.de':
return { strict: false, key: 'cookieAccepted', value: 'needed---piwik' };
case 'hackerrank.com':
return { strict: false, key: 'show_cookie_banner', value: 'false' };
case 'facebook.com':
case 'www.facebook.com':
return { strict: true, key: 'datr', value: 'accepted' };
case 'instagram.com':
case 'www.instagram.com':
return { strict: true, key: 'ig_did', value: 'accepted' };
case 'linkedin.com':
case 'www.linkedin.com':
return { strict: false, key: 'lidc', value: 'accepted' };
case 'reddit.com':
case 'www.reddit.com':
return { strict: false, key: 'eu_cookie', value: '{"opted":true}' };
case 'tiktok.com':
case 'www.tiktok.com':
return { strict: true, key: 'tt_webid', value: 'accepted' };
case 'netflix.com':
case 'www.netflix.com':
return { strict: false, key: 'netflix-cookie-consent', value: 'accepted' };
case 'spotify.com':
case 'www.spotify.com':
return { strict: false, key: 'sp_dc', value: 'accepted' };
case 'amazon.com':
case 'www.amazon.com':
return { strict: false, key: 'amazon-cookie-consent', value: 'accepted' };
case 'pinterest.com':
case 'www.pinterest.com':
return { strict: false, key: '_pinterest_sess', value: 'accepted' };
case 'twitch.tv':
case 'www.twitch.tv':
return { strict: false, key: 'twitch_cookie_consent', value: 'accepted' };
case 'github.com':
case 'www.github.com':
return { strict: false, key: '_gh_sess', value: 'accepted' };
case 'medium.com':
case 'www.medium.com':
return { strict: false, key: 'medium_cookie_consent', value: 'accepted' };
case 'quora.com':
case 'www.quora.com':
return { strict: false, key: 'm-b', value: 'accepted' };
case 'stackoverflow.com':
case 'www.stackoverflow.com':
return { strict: false, key: 'acct', value: 'accepted' };
case 'microsoft.com':
case 'www.microsoft.com':
return { strict: false, key: 'MUID', value: 'accepted' };
case 'apple.com':
case 'www.apple.com':
return { strict: false, key: 'geo', value: 'accepted' };
case 'dropbox.com':
case 'www.dropbox.com':
return { strict: false, key: 'dbx-consent', value: 'accepted' };
case 'booking.com':
case 'www.booking.com':
return { strict: false, key: 'bkng_consent', value: 'accepted' };
case 'vnexpress.net':
case 'www.vnexpress.net':
return { strict: false, key: 'vnexpress_cookie_consent', value: 'accepted' };
case 'thanhnien.vn':
case 'www.thanhnien.vn':
return { strict: false, key: 'thanhnien_cookie', value: 'accepted' };
case 'tuoitre.vn':
case 'www.tuoitre.vn':
return { strict: false, key: 'tuoitre_cookie', value: 'accepted' };
case 'tiki.vn':
case 'www.tiki.vn':
return { strict: false, key: 'tiki_cookie', value: 'accepted' };
case 'shopee.vn':
case 'www.shopee.vn':
return { strict: false, key: 'shopee_cookie', value: 'accepted' };
case 'lazada.vn':
case 'www.lazada.vn':
return { strict: false, key: 'lzd_cookie', value: 'accepted' };
case 'sendo.vn':
case 'www.sendo.vn':
return { strict: false, key: 'sendo_cookie', value: 'accepted' };
case 'thegioididong.com':
case 'www.thegioididong.com':
return { strict: false, key: 'tgdd_cookie', value: 'accepted' };
case 'fptshop.com.vn':
case 'www.fptshop.com.vn':
return { strict: false, key: 'fpt_cookie', value: 'accepted' };
case 'cellphones.com.vn':
case 'www.cellphones.com.vn':
return { strict: false, key: 'cps_cookie', value: 'accepted' };
case 'aliexpress.com':
case 'www.aliexpress.com':
return { strict: false, key: 'aep_usuc_f', value: 'accepted' };
case 'ebay.com':
case 'www.ebay.com':
return { strict: false, key: 'ebay_cookie_consent', value: 'accepted' };
case 'coursera.org':
case 'www.coursera.org':
return { strict: false, key: 'coursera_cookie', value: 'accepted' };
case 'udemy.com':
case 'www.udemy.com':
return { strict: false, key: 'ud_cookie', value: 'accepted' };
case 'bachhoaxanh.com':
case 'www.bachhoaxanh.com':
return { strict: false, key: 'bhx_cookie', value: 'accepted' };
case 'dienmayxanh.com':
case 'www.dienmayxanh.com':
return { strict: false, key: 'dmx_cookie', value: 'accepted' };
case 'nguyenkim.com':
case 'www.nguyenkim.com':
return { strict: false, key: 'nk_cookie', value: 'accepted' };
case 'dantri.com.vn':
case 'www.dantri.com.vn':
return { strict: false, key: 'dantri_cookie', value: 'accepted' };
case 'vietnamnet.vn':
case 'www.vietnamnet.vn':
return { strict: false, key: 'vietnamnet_cookie', value: 'accepted' };
case '24h.com.vn':
case 'www.24h.com.vn':
return { strict: false, key: '24h_cookie', value: 'accepted' };
case 'vietcombank.com.vn':
case 'www.vietcombank.com.vn':
return { strict: false, key: 'vcb_cookie', value: 'accepted' };
case 'techcombank.com.vn':
case 'www.techcombank.com.vn':
return { strict: false, key: 'tcb_cookie', value: 'accepted' };
case 'mbbank.com.vn':
case 'www.mbbank.com.vn':
return { strict: false, key: 'mb_cookie', value: 'accepted' };
case 'amazon.co.jp':
case 'www.amazon.co.jp':
return { strict: false, key: 'amazon_jp_cookie', value: 'accepted' };
case 'rakuten.co.jp':
case 'www.rakuten.co.jp':
return { strict: false, key: 'rakuten_jp_cookie', value: 'accepted' };
case 'taobao.com':
case 'www.taobao.com':
return { strict: false, key: 'taobao_cookie', value: 'accepted' };
case 'line.me':
case 'www.line.me':
return { strict: false, key: 'line_cookie', value: 'accepted' };
case 'weibo.com':
case 'www.weibo.com':
return { strict: false, key: 'weibo_cookie', value: 'accepted' };
case 'kakao.com':
case 'www.kakao.com':
return { strict: false, key: 'kakao_cookie', value: 'accepted' };
case 'yahoo.co.jp':
case 'www.yahoo.co.jp':
return { strict: false, key: 'yahoo_jp_cookie', value: 'accepted' };
case 'naver.com':
case 'www.naver.com':
return { strict: false, key: 'naver_cookie', value: 'accepted' };
case 'baidu.com':
case 'www.baidu.com':
return { strict: false, key: 'baidu_cookie', value: 'accepted' };
case 'zalando.com':
case 'www.zalando.com':
return { strict: false, key: 'zalando_cookie', value: 'accepted' };
case 'asos.com':
case 'www.asos.com':
return { strict: false, key: 'asos_cookie', value: 'accepted' };
case 'zara.com':
case 'www.zara.com':
return { strict: false, key: 'zara_cookie', value: 'accepted' };
case 'tmall.com':
case 'www.tmall.com':
return { strict: false, key: 'tmall_cookie', value: 'accepted' };
case 'jd.com':
case 'www.jd.com':
return { strict: false, key: 'jd_cookie', value: 'accepted' };
case 'sina.com.cn':
case 'www.sina.com.cn':
return { strict: false, key: 'sina_cookie', value: 'accepted' };
case 'qq.com':
case 'www.qq.com':
return { strict: false, key: 'qq_cookie', value: 'accepted' };
case '163.com':
case 'www.163.com':
return { strict: false, key: 'netease_cookie', value: 'accepted' };
case 'sohu.com':
case 'www.sohu.com':
return { strict: false, key: 'sohu_cookie', value: 'accepted' };
case 'bilibili.com':
case 'www.bilibili.com':
return { strict: false, key: 'bilibili_cookie', value: 'accepted' };
}
const parts = hostname.split('.');
if (parts.length > 2) {
parts.shift();
return getItem(parts.join('.'));
}
return false;
}
function _parent(element) {
if (element && element.parentNode) return element.parentNode;
return false;
}
function _iframe(iframe_selector, selector) {
var e = _sl(iframe_selector);
return e ? _sl(selector, e.contentDocument || e.contentWindow.contentDocument) : e;
}
// Cookie consent handling logic
let searchPairs = {
'.vn-cookie-banner': ['.vn-cookie-banner__reject', '.vn-cookie-banner__customize'],
'.vn-cookie-notice': ['.vn-cookie-notice__reject', '.vn-cookie-notice__settings'],
'.vn-cookie-consent': ['.vn-cookie-consent__reject', '.vn-cookie-consent__customize'],
'.vn-cookie-popup': ['.vn-cookie-popup__reject', '.vn-cookie-popup__settings'],
'.shopee-cookie-banner': ['.shopee-cookie-banner__reject', '.shopee-cookie-banner__settings'],
'.lazada-cookie-notice': ['.lazada-cookie-notice__reject', '.lazada-cookie-notice__settings'],
'.tiki-cookie-popup': ['.tiki-cookie-popup__reject', '.tiki-cookie-popup__settings'],
'.sendo-cookie-consent': ['.sendo-cookie-consent__reject', '.sendo-cookie-consent__settings'],
'.vnexpress-cookie': ['.vnexpress-cookie__reject', '.vnexpress-cookie__settings'],
'.tuoitre-cookie': ['.tuoitre-cookie__reject', '.tuoitre-cookie__settings'],
'.thanhnien-cookie': ['.thanhnien-cookie__reject', '.thanhnien-cookie__settings'],
'.dantri-cookie': ['.dantri-cookie__reject', '.dantri-cookie__settings'],
'.tgdd-cookie-notice': ['.tgdd-cookie-notice__reject', '.tgdd-cookie-notice__settings'],
'.fpt-cookie-popup': ['.fpt-cookie-popup__reject', '.fpt-cookie-popup__settings'],
'.cps-cookie-consent': ['.cps-cookie-consent__reject', '.cps-cookie-consent__settings'],
'.vcb-cookie-notice': ['.vcb-cookie-notice__reject', '.vcb-cookie-notice__settings'],
'.tcb-cookie-popup': ['.tcb-cookie-popup__reject', '.tcb-cookie-popup__settings'],
'.mb-cookie-consent': ['.mb-cookie-consent__reject', '.mb-cookie-consent__settings'],
'div[class*="consent"]': ['button[class*="reject"]', 'button[class*="decline"]', 'button[class*="settings"]'],
'div[class*="notice"]': ['button[class*="reject"]', 'button[class*="decline"]', 'button[class*="settings"]'],
'div[class*="popup"]': ['button[class*="reject"]', 'button[class*="decline"]', 'button[class*="settings"]'],
'div[class*="banner"]': ['button[class*="reject"]', 'button[class*="decline"]', 'button[class*="settings"]'],
};
let searchGroups = [
'.qc-cmp2-summary-buttons button[mode="secondary"],\
.qc-cmp2-buttons-desktop > button:first-child,\
#didomi-popup .didomi-button-highlight:not([class*="paywall"]):not([class*="disagree"]),\
#rgpd_video .rgpd-mask a[data-rgpd-consent],\
.cli-barmodal-open #wt-cli-privacy-save-btn,\
.js--modal[style*="block"] .cookie-permission--accept-button,\
.gdpr-modal-rider .btn-cookieaccept,\
.js-cookiewall #sel-test-accept-cookies-button,\
#mpo[style*="block"] .submit.modal-privacy__btn[onclick*="privacyframe.accept"],\
.lightbox--cookie-consent .btn-cta,\
.lightbox.cookie-consent .cookie-consent-button-decline,\
.js-modal-gdpr.is-active .btn[data-level="2"],\
#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowallSelection,\
#cookieNotificationModal.in .btn.accept-cookie,\
.has-ccwindow .cc-compliance .cc-dismiss,\
.ds2-cookie-disclaimer--slidedown .ds2-cookie-disclaimer-js--submit,\
#mdlCookieCompliance.in .cookieClose,\
#cookieModal.in .js-acceptDefaultCookie,\
.c-cookiebutton .c-cookiebutton__close,\
#normativa_cookies.in .btn,\
#cookiewall.in .btn-primary,\
.outerCookieBar .EuCookieBar__cookieButton,\
#TOS-POPUP .rhododendron-popup__button--agree,\
#cookie-wall #accept-cookies,\
#popup-wrapper .button[href*="/cookies.consent.php"],\
.reveal.cookies[style*="block"] button[click*="aceptaCookies"],\
.mnd-cookie-modal[style*="block"] .btn.is--primary,\
.cookieHandler.cookieHandler--modalOpen #acceptAllCookies,\
.gdpr-modal--active .btn--primary,\
#dpi-banner:not(.hidden) #btn-agree-cookie,\
.gh-banner.gh-banner-active #gh-cookiebanner-close,\
#mrktpref.notification-bar .btn-success,\
#PopinGDPRCookie[style*="block"] .jsbd-popin-ok,\
#modal-rodo.in .btn-primary,\
.cookie-compliance-modal.in .btn-primary,\
.cookieconsent.show .btn[data-dm*="accept"],\
.cookie-wall-modal.in .btn.ja,\
#modal-consent.in .modal-consent-accept,\
.rodo #cookies.in .btn-primary,\
.js-cookie-alert.in .js-cookie-alert-accept,\
#modal_gdpr_intro_popup.in #gdpr-modal-btn-ok-agree,\
#consentButtonContainer > button[onclick*="sendAndRedirect"],\
#eu-consent[style*="block"] .btn.yes,\
.modal--gdpr.is-open .js-gdpr-consent,\
#cookiePopupModal.in .cookiepopup-agreed,\
.polityka-cookie-rodo[style*="block"] .button-zgoda,\
.ui-dialog.consent-modal[style*="block"] .js-btn-agree,\
#up-cookie.active .button[onclick*="setCookiePreference"],\
.RodoModal.in .close,\
.consent-popup form[action*="cookie-consent"] .consent-popup__button,\
#consent form[action*="cookie-consent"] .one-btn,\
#cookiewall-wrapper .button[href*="accept"],\
#cookieChoiceButtonAccept,\
.mod-cookie-consent[style*="block"] .btn-all-cookies,\
.c-layer--consent .layer-button--accept,\
.button.button-ok[onclick*="acceptAVG"],\
#meredithGdprConsentFormButton,\
#advanced-cookie-modal.in .cookie-accept,\
.show-modal .cookie-settings-manager-container .initial-dialog .js-accept-button,\
.cookie-settings-manager-container .initial-dialog[style*="block"] .js-accept-button,\
.gdprLightbox[data-module="gdprLightbox"] ._type_gdpr_agree,\
.cookie.showa #Row1_Column1_Cell1_CookieSettings_AdvancedSaveAccept,\
#core-cookie-container[style*="block"] .btn--agree,\
.cookie-consent-modal._show .action-primary,\
#dsgvoModal.show #dsvgo-banner__button,\
.basicLightbox--visible #accept-all-gdpr,\
#gdpr-modal.in .gdpr-modal__btn--accept,\
.cookiehint .btn.cookieagree,\
#cookiealert .modal.in .btn[href*="accept"],\
#lml-data-consent-accept,\
#CBCookieMsg.in .btn[onclick*="approveCookies"],\
#cookiewall-container .button[name="submit"],\
#cookie_disclaimer.in .cookie_disclaimer_button,\
.m-cookie.iziModal[style*="block"] .m-cookie__save2.button,\
kamino-cookie-policy .mat-raised-button,\
#surbma-gpga-modal[style*="block"] button,\
#GDPR.overlayBox .menuButton,\
#cookiebar .cookie-selection-button.accept,\
.modal.in .btn.close-modal-cookie,\
#consent-module[style*="block"] #consent-module-text-button,\
.modal #consentButton,\
#consent-modal[style*="block"] .lm_modal__modal__content__body__buttons__ok,\
.cookiesOverlay3Box #cookiesConsentOK,\
.bemCookieOverlay--activePopup .bemCookieOverlay__btn--save,\
#root main ~ div [data-gi-selector="reject-all-cookies"] ~ div a,\
.cookies-management .cookies-deny,\
.offcanvas.is-open .js-offcanvas-cookie-submit,\
.force--consent.show--consent #cs_save__btn,\
.force--consent.show--consent #s-sv-bn,\
#cookieNoticeModal.vrm-reveal[style*="block"] .vrm-reveal__icon--close',
'.cookie-banner .cookie-banner__buttons .cookie-banner__button--reject,\
.cookie-consent-banner .cookie-consent-banner__reject,\
.cookie-notification .cookie-notification__buttons .cookie-notification__reject,\
.cookie-policy-banner .cookie-policy-banner__buttons .cookie-policy-banner__reject,\
.cookie-warning .cookie-warning__buttons .cookie-warning__reject,\
.cookie-notice .cookie-notice__buttons .cookie-notice__reject,\
.cookie-alert .cookie-alert__buttons .cookie-alert__reject,\
.cookie-popup .cookie-popup__buttons .cookie-popup__reject,\
.cookie-modal .cookie-modal__buttons .cookie-modal__reject,\
.cookie-dialog .cookie-dialog__buttons .cookie-dialog__reject,\
.gdpr-banner .gdpr-banner__buttons .gdpr-banner__reject,\
.gdpr-modal .gdpr-modal__buttons .gdpr-modal__reject,\
.gdpr-notice .gdpr-notice__buttons .gdpr-notice__reject,\
.gdpr-popup .gdpr-popup__buttons .gdpr-popup__reject,\
.gdpr-dialog .gdpr-dialog__buttons .gdpr-dialog__reject,\
.privacy-banner .privacy-banner__buttons .privacy-banner__reject,\
.privacy-modal .privacy-modal__buttons .privacy-modal__reject,\
.privacy-notice .privacy-notice__buttons .privacy-notice__reject,\
.privacy-popup .privacy-popup__buttons .privacy-popup__reject,\
.privacy-dialog .privacy-dialog__buttons .privacy-dialog__reject',
'.consent-banner .consent-banner__buttons .consent-banner__reject,\
.consent-modal .consent-modal__buttons .consent-modal__reject,\
.consent-notice .consent-notice__buttons .consent-notice__reject,\
.consent-popup .consent-popup__buttons .consent-popup__reject,\
.consent-dialog .consent-dialog__buttons .consent-dialog__reject,\
.tracking-banner .tracking-banner__buttons .tracking-banner__reject,\
.tracking-modal .tracking-modal__buttons .tracking-modal__reject,\
.tracking-notice .tracking-notice__buttons .tracking-notice__reject,\
.tracking-popup .tracking-popup__buttons .tracking-popup__reject,\
.tracking-dialog .tracking-dialog__buttons .tracking-dialog__reject',
'.cookie-settings-modal .cookie-settings__reject,\
.cookie-settings-modal .cookie-settings__customize,\
.cookie-preferences-modal .cookie-preferences__reject,\
.cookie-preferences-modal .cookie-preferences__customize,\
.cookie-manager-modal .cookie-manager__reject,\
.cookie-manager-modal .cookie-manager__customize,\
.cookie-control-modal .cookie-control__reject,\
.cookie-control-modal .cookie-control__customize,\
.cookie-options-modal .cookie-options__reject,\
.cookie-options-modal .cookie-options__customize',
'.data-privacy-modal .data-privacy__reject,\
.data-privacy-modal .data-privacy__customize,\
.data-protection-modal .data-protection__reject,\
.data-protection-modal .data-protection__customize,\
.data-consent-modal .data-consent__reject,\
.data-consent-modal .data-consent__customize,\
.data-settings-modal .data-settings__reject,\
.data-settings-modal .data-settings__customize,\
.data-preferences-modal .data-preferences__reject,\
.data-preferences-modal .data-preferences__customize',
'.privacy-manager-modal .privacy-manager__reject,\
.privacy-manager-modal .privacy-manager__customize,\
.privacy-settings-modal .privacy-settings__reject,\
.privacy-settings-modal .privacy-settings__customize,\
.privacy-options-modal .privacy-options__reject,\
.privacy-options-modal .privacy-options__customize,\
.privacy-control-modal .privacy-control__reject,\
.privacy-control-modal .privacy-control__customize,\
.privacy-preferences-modal .privacy-preferences__reject,\
.privacy-preferences-modal .privacy-preferences__customize',
'.consent-manager-modal .consent-manager__reject,\
.consent-manager-modal .consent-manager__customize,\
.consent-settings-modal .consent-settings__reject,\
.consent-settings-modal .consent-settings__customize,\
.consent-options-modal .consent-options__reject,\
.consent-options-modal .consent-options__customize,\
.consent-control-modal .consent-control__reject,\
.consent-control-modal .consent-control__customize,\
.consent-preferences-modal .consent-preferences__reject,\
.consent-preferences-modal .consent-preferences__customize',
'.tracking-manager-modal .tracking-manager__reject,\
.tracking-manager-modal .tracking-manager__customize,\
.tracking-settings-modal .tracking-settings__reject,\
.tracking-settings-modal .tracking-settings__customize,\
.tracking-options-modal .tracking-options__reject,\
.tracking-options-modal .tracking-options__customize,\
.tracking-control-modal .tracking-control__reject,\
.tracking-control-modal .tracking-control__customize,\
.tracking-preferences-modal .tracking-preferences__reject,\
.tracking-preferences-modal .tracking-preferences__customize',
'.gdpr-manager-modal .gdpr-manager__reject,\
.gdpr-manager-modal .gdpr-manager__customize,\
.gdpr-settings-modal .gdpr-settings__reject,\
.gdpr-settings-modal .gdpr-settings__customize,\
.gdpr-options-modal .gdpr-options__reject,\
.gdpr-options-modal .gdpr-options__customize,\
.gdpr-control-modal .gdpr-control__reject,\
.gdpr-control-modal .gdpr-control__customize,\
.gdpr-preferences-modal .gdpr-preferences__reject,\
.gdpr-preferences-modal .gdpr-preferences__customize',
'div[class*="cookie-banner"] button[class*="reject"],\
div[class*="cookie-banner"] button[class*="decline"],\
div[class*="cookie-banner"] button[class*="settings"],\
div[id*="cookie-banner"] button[class*="reject"],\
div[id*="cookie-banner"] button[class*="decline"],\
div[id*="cookie-banner"] button[class*="settings"]',
'div[class*="cookie-consent"] button[class*="reject"],\
div[class*="cookie-consent"] button[class*="decline"],\
div[class*="cookie-consent"] button[class*="settings"],\
div[id*="cookie-consent"] button[class*="reject"],\
div[id*="cookie-consent"] button[class*="decline"],\
div[id*="cookie-consent"] button[class*="settings"]',
'div[class*="cookie-notice"] button[class*="reject"],\
div[class*="cookie-notice"] button[class*="decline"],\
div[class*="cookie-notice"] button[class*="settings"],\
div[id*="cookie-notice"] button[class*="reject"],\
div[id*="cookie-notice"] button[class*="decline"],\
div[id*="cookie-notice"] button[class*="settings"]',
'[data-*="cookie"] button[data-*="reject"],\
[data-*="cookie"] button[data-*="decline"],\
[data-*="cookie"] button[data-*="settings"],\
[data-*="gdpr"] button[data-*="reject"],\
[data-*="gdpr"] button[data-*="decline"],\
[data-*="gdpr"] button[data-*="settings"]',
'div[class*="cookie-layer"] button[class*="reject"],\
div[class*="cookie-layer"] button[class*="decline"],\
div[class*="cookie-layer"] button[class*="settings"],\
div[id*="cookie-layer"] button[class*="reject"],\
div[id*="cookie-layer"] button[class*="decline"],\
div[id*="cookie-layer"] button[class*="settings"]',
'div[class*="cookie-section"] button[class*="reject"],\
div[class*="cookie-section"] button[class*="decline"],\
div[class*="cookie-section"] button[class*="settings"],\
div[id*="cookie-section"] button[class*="reject"],\
div[id*="cookie-section"] button[class*="decline"],\
div[id*="cookie-section"] button[class*="settings"]',
'div[class*="cookie-container"] button[class*="reject"],\
div[class*="cookie-container"] button[class*="decline"],\
div[class*="cookie-container"] button[class*="settings"],\
div[id*="cookie-container"] button[class*="reject"],\
div[id*="cookie-container"] button[class*="decline"],\
div[id*="cookie-container"] button[class*="settings"]',
'[data-purpose*="cookie"] button[data-purpose*="reject"],\
[data-purpose*="cookie"] button[data-purpose*="decline"],\
[data-purpose*="cookie"] button[data-purpose*="settings"],\
[data-ref*="cookie"] button[data-ref*="reject"],\
[data-ref*="cookie"] button[data-ref*="decline"],\
[data-ref*="cookie"] button[data-ref*="settings"]',
'[id*="cookie-manager"] button[id*="reject"],\
[id*="cookie-manager"] button[id*="decline"],\
[id*="cookie-manager"] button[id*="settings"],\
[id*="cookie-control"] button[id*="reject"],\
[id*="cookie-control"] button[id*="decline"],\
[id*="cookie-control"] button[id*="settings"]',
'div[class*="vn-cookie"] button[class*="reject"],\
div[class*="vn-cookie"] button[class*="decline"],\
div[class*="vn-cookie"] button[class*="settings"],\
div[id*="vn-cookie"] button[class*="reject"],\
div[id*="vn-cookie"] button[class*="decline"],\
div[id*="vn-cookie"] button[class*="settings"]',
'div[class*="ecommerce"] button[class*="cookie-reject"],\
div[class*="ecommerce"] button[class*="cookie-decline"],\
div[class*="ecommerce"] button[class*="cookie-settings"],\
div[id*="ecommerce"] button[class*="cookie-reject"],\
div[id*="ecommerce"] button[class*="cookie-decline"],\
div[id*="ecommerce"] button[class*="cookie-settings"]',
'div[class*="news"] button[class*="cookie-reject"],\
div[class*="news"] button[class*="cookie-decline"],\
div[class*="news"] button[class*="cookie-settings"],\
div[id*="news"] button[class*="cookie-reject"],\
div[id*="news"] button[class*="cookie-decline"],\
div[id*="news"] button[class*="cookie-settings"]',
'div[class*="retail"] button[class*="cookie-reject"],\
div[class*="retail"] button[class*="cookie-decline"],\
div[class*="retail"] button[class*="cookie-settings"],\
div[id*="retail"] button[class*="cookie-reject"],\
div[id*="retail"] button[class*="cookie-decline"],\
div[id*="retail"] button[class*="cookie-settings"]',
'div[class*="gdpr"] button[class*="reject"],\
div[class*="gdpr"] button[class*="decline"],\
div[class*="gdpr"] button[class*="settings"],\
div[id*="gdpr"] button[class*="reject"],\
div[id*="gdpr"] button[class*="decline"],\
div[id*="gdpr"] button[class*="settings"]',
'div[class*="privacy"] button[class*="reject"],\
div[class*="privacy"] button[class*="decline"],\
div[class*="privacy"] button[class*="settings"],\
div[id*="privacy"] button[class*="reject"],\
div[id*="privacy"] button[class*="decline"],\
div[id*="privacy"] button[class*="settings"]',
'div[class*="bank"] button[class*="cookie-reject"],\
div[class*="bank"] button[class*="cookie-decline"],\
div[class*="bank"] button[class*="cookie-settings"],\
div[id*="bank"] button[class*="cookie-reject"],\
div[id*="bank"] button[class*="cookie-decline"],\
div[id*="bank"] button[class*="cookie-settings"]',
'div[class*="consent"] button[class*="reject"],\
div[class*="consent"] button[class*="decline"],\
div[class*="consent"] button[class*="settings"],\
div[id*="consent"] button[class*="reject"],\
div[id*="consent"] button[class*="decline"],\
div[id*="consent"] button[class*="settings"]',
'div[class*="notice"] button[class*="reject"],\
div[class*="notice"] button[class*="decline"],\
div[class*="notice"] button[class*="settings"],\
div[id*="notice"] button[class*="reject"],\
div[id*="notice"] button[class*="decline"],\
div[id*="notice"] button[class*="settings"]',
'div[class*="popup"] button[class*="reject"],\
div[class*="popup"] button[class*="decline"],\
div[class*="popup"] button[class*="settings"],\
div[id*="popup"] button[class*="reject"],\
div[id*="popup"] button[class*="decline"],\
div[id*="popup"] button[class*="settings"]',
'div[class*="eu-cookie-banner"] button[class*="reject"],\
div[class*="eu-cookie-banner"] button[class*="settings"]',
'div[class*="gdpr-notice"] button[class*="reject"],\
div[class*="gdpr-notice"] button[class*="settings"]',
'div[class*="privacy-consent"] button[class*="reject"],\
div[class*="privacy-consent"] button[class*="settings"]',
'div[class*="asia"] button[class*="cookie-reject"],\
div[class*="asia"] button[class*="cookie-decline"],\
div[class*="asia"] button[class*="cookie-settings"]',
'div[class*="europe"] button[class*="cookie-reject"],\
div[class*="europe"] button[class*="cookie-decline"],\
div[class*="europe"] button[class*="cookie-settings"]',
'div[class*="global"] button[class*="cookie-reject"],\
div[class*="global"] button[class*="cookie-decline"],\
div[class*="global"] button[class*="cookie-settings"]',
'div[class*="america"] button[class*="cookie-reject"],\
div[class*="america"] button[class*="cookie-decline"],\
div[class*="america"] button[class*="cookie-settings"]',
'div[class*="oceania"] button[class*="cookie-reject"],\
div[class*="oceania"] button[class*="cookie-decline"],\
div[class*="oceania"] button[class*="cookie-settings"]',
];
let currentChainElement = 0;
const classname = Math.random()
.toString(36)
.replace(/[^a-z]+/g, '');
// Search loop function
let searchGroupsLength = searchGroups.length,
searchPairsKeys = Object.keys(searchPairs),
searchPairsJoinedKeys = searchPairsKeys.join(','),
timeoutDuration = 300;
function querySelectorAllShadowRoot(selector, root = document) {
const elements = [];
const findElements = node => {
if (node.shadowRoot) {
node.shadowRoot.querySelectorAll(selector).forEach(el => elements.push(el));
node.shadowRoot.querySelectorAll('*').forEach(findElements);
}
};
root.querySelectorAll('*').forEach(findElements);
return elements;
}
function searchLoop(counter) {
if (document.cookie.indexOf('cookie_consent') !== -1) {
return;
}
const dynamicTimeout = Math.min(timeoutDuration * (counter + 1), 2000);
setTimeout(function () {
document.querySelectorAll(searchPairsJoinedKeys).forEach(function (box) {
searchPairsKeys.forEach(function (selector) {
if (box.matches(selector)) {
const shadowElements = querySelectorAllShadowRoot(searchPairs[selector].join(','), box);
shadowElements.forEach(button => {
if (button.click && !button.classList.contains(classname)) {
button.classList.add(classname);
if (typeof chrome == 'object' && chrome.runtime) chrome.runtime.sendMessage({ command: 'cookie_warning_dismissed', url: document.location.href });
button.click();
if (selector != '.message-container' && button.getAttribute('href') != '#cookieman-settings')
setTimeout(function () {
if (button) button.click();
}, 500);
timeoutDuration += 500;
}
});
}
});
});
document.querySelectorAll(searchGroups[counter % searchGroupsLength]).forEach(function (element) {
if (element.click && !element.classList.contains(classname)) {
element.classList.add(classname);
if (typeof chrome == 'object' && chrome.runtime) chrome.runtime.sendMessage({ command: 'cookie_warning_dismissed', url: document.location.href });
element.click();
if (element.getAttribute('aria-pressed') != 'true')
setTimeout(function () {
if (element) element.click();
}, 500);
timeoutDuration += 500;
}
});
if (counter < 100 * searchGroupsLength) {
searchLoop(counter + 1);
}
}, dynamicTimeout);
}
// Embeds handling
function handleEmbeds() {
var l = document.location,
is_audioboom = false,
is_dailymotion = false,
is_dailybuzz = false,
is_playerclipslaliga = false;
switch (l.hostname) {
case 'embeds.audioboom.com':
is_audioboom = true;
break;
case 'dailymotion.com':
case 'www.dailymotion.com':
is_dailymotion = l.pathname.indexOf('/embed') === 0;
break;
case 'geo.dailymotion.com':
is_dailymotion = l.pathname.indexOf('/player') === 0;
break;
case 'dailybuzz.nl':
is_dailybuzz = l.pathname.indexOf('/buzz/embed') === 0;
break;
case 'playerclipslaliga.tv':
is_playerclipslaliga = true;
break;
}
function searchEmbeds() {
setTimeout(function () {
if (is_audioboom) {
document.querySelectorAll('div[id^="cookie-modal"] .modal[style*="block"] .btn.mrs:not(.' + classname + ')').forEach(function (button) {
button.className += ' ' + classname;
button.click();
});
} else if (is_dailymotion) {
document.querySelectorAll('.np_DialogConsent-accept:not(.' + classname + '), .consent_screen-accept:not(.' + classname + ')').forEach(function (button) {
button.className += ' ' + classname;
button.click();
});
} else if (is_dailybuzz) {
document.querySelectorAll('#ask-consent #accept:not(.' + classname + ')').forEach(function (button) {
button.className += ' ' + classname;
button.click();
});
} else if (is_playerclipslaliga) {
document.querySelectorAll('#cookies button[onclick*="saveCookiesSelection"]:not(.' + classname + ')').forEach(function (button) {
button.className += ' ' + classname;
button.click();
});
} else {
return;
}
searchEmbeds();
}, 1000);
}
searchEmbeds();
}
// Initialize
var start = setInterval(function () {
var html = document.querySelector('html');
if (!html || /idc0_350/.test(html.className)) return;
clearInterval(start);
html.className += ' idc0_350';
searchLoop(0);
handleEmbeds();
}, 500);
var hostname = document.location.hostname.replace(/^w{2,3}\d*\./i, ''),
items = getItem(hostname);
if (items) {
(items instanceof Array ? items : [items]).forEach(function (item) {
let value = localStorage.getItem(item.key);
if (value == null || (item.strict && value != item.value)) {
localStorage.setItem(item.key, item.value);
counter++;
}
});
if (counter > 0) document.location.reload();
}
})();
@@ -0,0 +1,704 @@
// ==UserScript==
// @name Return YouTube Dislike
// @namespace https://www.returnyoutubedislike.com/
// @homepage https://www.returnyoutubedislike.com/
// @version 3.1.5
// @encoding utf-8
// @description Return of the YouTube Dislike, Based off https://www.returnyoutubedislike.com/
// @icon https://github.com/Anarios/return-youtube-dislike/raw/main/Icons/Return%20Youtube%20Dislike%20-%20Transparent.png
// @author Anarios & JRWR
// @match *://*.youtube.com/*
// @exclude *://music.youtube.com/*
// @exclude *://*.music.youtube.com/*
// @compatible chrome
// @compatible firefox
// @compatible opera
// @compatible safari
// @compatible edge
// @grant GM.xmlHttpRequest
// @connect youtube.com
// @grant GM_addStyle
// @run-at document-end
// @downloadURL https://update.greasyfork.org/scripts/436115/Return%20YouTube%20Dislike.user.js
// @updateURL https://update.greasyfork.org/scripts/436115/Return%20YouTube%20Dislike.meta.js
// ==/UserScript==
const extConfig = {
// BEGIN USER OPTIONS
// You may change the following variables to allowed values listed in the corresponding brackets (* means default). Keep the style and keywords intact.
showUpdatePopup: false, // [true, false*] Show a popup tab after extension update (See what's new)
disableVoteSubmission: false, // [true, false*] Disable like/dislike submission (Stops counting your likes and dislikes)
disableLogging: true, // [true*, false] Disable Logging API Response in JavaScript Console.
coloredThumbs: false, // [true, false*] Colorize thumbs (Use custom colors for thumb icons)
coloredBar: false, // [true, false*] Colorize ratio bar (Use custom colors for ratio bar)
colorTheme: "classic", // [classic*, accessible, neon] Color theme (red/green, blue/yellow, pink/cyan)
numberDisplayFormat: "compactShort", // [compactShort*, compactLong, standard] Number format (For non-English locale users, you may be able to improve appearance with a different option. Please file a feature request if your locale is not covered)
numberDisplayRoundDown: true, // [true*, false] Round down numbers (Show rounded down numbers)
tooltipPercentageMode: "none", // [none*, dash_like, dash_dislike, both, only_like, only_dislike] Mode of showing percentage in like/dislike bar tooltip.
numberDisplayReformatLikes: false, // [true, false*] Re-format like numbers (Make likes and dislikes format consistent)
rateBarEnabled: false, // [true, false*] Enables ratio bar under like/dislike buttons
// END USER OPTIONS
};
const LIKED_STATE = "LIKED_STATE";
const DISLIKED_STATE = "DISLIKED_STATE";
const NEUTRAL_STATE = "NEUTRAL_STATE";
let previousState = 3; //1=LIKED, 2=DISLIKED, 3=NEUTRAL
let likesvalue = 0;
let dislikesvalue = 0;
let preNavigateLikeButton = null;
let isMobile = location.hostname == "m.youtube.com";
let isShorts = () => location.pathname.startsWith("/shorts");
let mobileDislikes = 0;
function cLog(text, subtext = "") {
if (!extConfig.disableLogging) {
subtext = subtext.trim() === "" ? "" : `(${subtext})`;
console.log(`[Return YouTube Dislikes] ${text} ${subtext}`);
}
}
function isInViewport(element) {
const rect = element.getBoundingClientRect();
const height = innerHeight || document.documentElement.clientHeight;
const width = innerWidth || document.documentElement.clientWidth;
return (
// When short (channel) is ignored, the element (like/dislike AND short itself) is
// hidden with a 0 DOMRect. In this case, consider it outside of Viewport
!(rect.top == 0 && rect.left == 0 && rect.bottom == 0 && rect.right == 0) &&
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= height &&
rect.right <= width
);
}
function getButtons() {
if (isShorts()) {
let elements = document.querySelectorAll(
isMobile ? "ytm-like-button-renderer" : "#like-button > ytd-like-button-renderer",
);
for (let element of elements) {
if (isInViewport(element)) {
return element;
}
}
}
if (isMobile) {
return (
document.querySelector(".slim-video-action-bar-actions .segmented-buttons") ??
document.querySelector(".slim-video-action-bar-actions")
);
}
if (document.getElementById("menu-container")?.offsetParent === null) {
return (
document.querySelector("ytd-menu-renderer.ytd-watch-metadata > div") ??
document.querySelector("ytd-menu-renderer.ytd-video-primary-info-renderer > div")
);
} else {
return document.getElementById("menu-container")?.querySelector("#top-level-buttons-computed");
}
}
function getDislikeButton() {
if (getButtons().children[0].tagName === "YTD-SEGMENTED-LIKE-DISLIKE-BUTTON-RENDERER") {
if (getButtons().children[0].children[1] === undefined) {
return document.querySelector("#segmented-dislike-button");
} else {
return getButtons().children[0].children[1];
}
} else {
if (getButtons().querySelector("segmented-like-dislike-button-view-model")) {
const dislikeViewModel = getButtons().querySelector("dislike-button-view-model");
if (!dislikeViewModel) cLog("Dislike button wasn't added to DOM yet...");
return dislikeViewModel;
} else {
return getButtons().children[1];
}
}
}
function getLikeButton() {
return getButtons().children[0].tagName === "YTD-SEGMENTED-LIKE-DISLIKE-BUTTON-RENDERER"
? document.querySelector("#segmented-like-button") !== null
? document.querySelector("#segmented-like-button")
: getButtons().children[0].children[0]
: getButtons().querySelector("like-button-view-model") ?? getButtons().children[0];
}
function getLikeTextContainer() {
return (
getLikeButton().querySelector("#text") ??
getLikeButton().getElementsByTagName("yt-formatted-string")[0] ??
getLikeButton().querySelector("span[role='text']")
);
}
function getDislikeTextContainer() {
const dislikeButton = getDislikeButton();
let result =
dislikeButton?.querySelector("#text") ??
dislikeButton?.getElementsByTagName("yt-formatted-string")[0] ??
dislikeButton?.querySelector("span[role='text']");
if (result === null) {
let textSpan = document.createElement("span");
textSpan.id = "text";
textSpan.style.marginLeft = "6px";
dislikeButton?.querySelector("button").appendChild(textSpan);
if (dislikeButton) dislikeButton.querySelector("button").style.width = "auto";
result = textSpan;
}
return result;
}
function createObserver(options, callback) {
const observerWrapper = new Object();
observerWrapper.options = options;
observerWrapper.observer = new MutationObserver(callback);
observerWrapper.observe = function (element) {
this.observer.observe(element, this.options);
};
observerWrapper.disconnect = function () {
this.observer.disconnect();
};
return observerWrapper;
}
let shortsObserver = null;
if (isShorts() && !shortsObserver) {
cLog("Initializing shorts mutation observer");
shortsObserver = createObserver(
{
attributes: true,
},
(mutationList) => {
mutationList.forEach((mutation) => {
if (
mutation.type === "attributes" &&
mutation.target.nodeName === "TP-YT-PAPER-BUTTON" &&
mutation.target.id === "button"
) {
cLog("Short thumb button status changed");
if (mutation.target.getAttribute("aria-pressed") === "true") {
mutation.target.style.color =
mutation.target.parentElement.parentElement.id === "like-button"
? getColorFromTheme(true)
: getColorFromTheme(false);
} else {
mutation.target.style.color = "unset";
}
return;
}
cLog("Unexpected mutation observer event: " + mutation.target + mutation.type);
});
},
);
}
function isVideoLiked() {
if (isMobile) {
return getLikeButton().querySelector("button").getAttribute("aria-label") == "true";
}
return getLikeButton().classList.contains("style-default-active");
}
function isVideoDisliked() {
if (isMobile) {
return getDislikeButton()?.querySelector("button").getAttribute("aria-label") == "true";
}
return getDislikeButton()?.classList.contains("style-default-active");
}
function isVideoNotLiked() {
if (isMobile) {
return !isVideoLiked();
}
return getLikeButton().classList.contains("style-text");
}
function isVideoNotDisliked() {
if (isMobile) {
return !isVideoDisliked();
}
return getDislikeButton()?.classList.contains("style-text");
}
function checkForUserAvatarButton() {
if (isMobile) {
return;
}
if (document.querySelector("#avatar-btn")) {
return true;
} else {
return false;
}
}
function getState() {
if (isVideoLiked()) {
return LIKED_STATE;
}
if (isVideoDisliked()) {
return DISLIKED_STATE;
}
return NEUTRAL_STATE;
}
function setLikes(likesCount) {
if (isMobile) {
getButtons().children[0].querySelector(".button-renderer-text").innerText = likesCount;
return;
}
getLikeTextContainer().innerText = likesCount;
}
function setDislikes(dislikesCount) {
if (isMobile) {
mobileDislikes = dislikesCount;
return;
}
const _container = getDislikeTextContainer();
_container?.removeAttribute("is-empty");
if (_container?.innerText !== dislikesCount) {
_container.innerText = dislikesCount;
}
}
function getLikeCountFromButton() {
try {
if (isShorts()) {
//Youtube Shorts don't work with this query. It's not necessary; we can skip it and still see the results.
//It should be possible to fix this function, but it's not critical to showing the dislike count.
return false;
}
let likeButton =
getLikeButton().querySelector("yt-formatted-string#text") ?? getLikeButton().querySelector("button");
let likesStr = likeButton.getAttribute("aria-label").replace(/\D/g, "");
return likesStr.length > 0 ? parseInt(likesStr) : false;
} catch {
return false;
}
}
(typeof GM_addStyle != "undefined"
? GM_addStyle
: (styles) => {
let styleNode = document.createElement("style");
styleNode.type = "text/css";
styleNode.innerText = styles;
document.head.appendChild(styleNode);
})(`
#return-youtube-dislike-bar-container {
background: var(--yt-spec-icon-disabled);
border-radius: 2px;
}
#return-youtube-dislike-bar {
background: var(--yt-spec-text-primary);
border-radius: 2px;
transition: all 0.15s ease-in-out;
}
.ryd-tooltip {
position: absolute;
display: block;
height: 2px;
bottom: -10px;
}
.ryd-tooltip-bar-container {
width: 100%;
height: 2px;
position: absolute;
padding-top: 6px;
padding-bottom: 12px;
top: -6px;
}
ytd-menu-renderer.ytd-watch-metadata {
overflow-y: visible !important;
}
#top-level-buttons-computed {
position: relative !important;
}
`);
function createRateBar(likes, dislikes) {
if (isMobile || !extConfig.rateBarEnabled) {
return;
}
let rateBar = document.getElementById("return-youtube-dislike-bar-container");
const widthPx = getLikeButton().clientWidth + (getDislikeButton()?.clientWidth ?? 52);
const widthPercent = likes + dislikes > 0 ? (likes / (likes + dislikes)) * 100 : 50;
var likePercentage = parseFloat(widthPercent.toFixed(1));
const dislikePercentage = (100 - likePercentage).toLocaleString();
likePercentage = likePercentage.toLocaleString();
var tooltipInnerHTML;
switch (extConfig.tooltipPercentageMode) {
case "dash_like":
tooltipInnerHTML = `${likes.toLocaleString()}&nbsp;/&nbsp;${dislikes.toLocaleString()}&nbsp;&nbsp;-&nbsp;&nbsp;${likePercentage}%`;
break;
case "dash_dislike":
tooltipInnerHTML = `${likes.toLocaleString()}&nbsp;/&nbsp;${dislikes.toLocaleString()}&nbsp;&nbsp;-&nbsp;&nbsp;${dislikePercentage}%`;
break;
case "both":
tooltipInnerHTML = `${likePercentage}%&nbsp;/&nbsp;${dislikePercentage}%`;
break;
case "only_like":
tooltipInnerHTML = `${likePercentage}%`;
break;
case "only_dislike":
tooltipInnerHTML = `${dislikePercentage}%`;
break;
default:
tooltipInnerHTML = `${likes.toLocaleString()}&nbsp;/&nbsp;${dislikes.toLocaleString()}`;
}
if (!rateBar && !isMobile) {
let colorLikeStyle = "";
let colorDislikeStyle = "";
if (extConfig.coloredBar) {
colorLikeStyle = "; background-color: " + getColorFromTheme(true);
colorDislikeStyle = "; background-color: " + getColorFromTheme(false);
}
getButtons().insertAdjacentHTML(
"beforeend",
`
<div class="ryd-tooltip" style="width: ${widthPx}px">
<div class="ryd-tooltip-bar-container">
<div
id="return-youtube-dislike-bar-container"
style="width: 100%; height: 2px;${colorDislikeStyle}"
>
<div
id="return-youtube-dislike-bar"
style="width: ${widthPercent}%; height: 100%${colorDislikeStyle}"
></div>
</div>
</div>
<tp-yt-paper-tooltip position="top" id="ryd-dislike-tooltip" class="style-scope ytd-sentiment-bar-renderer" role="tooltip" tabindex="-1">
<!--css-build:shady-->${tooltipInnerHTML}
</tp-yt-paper-tooltip>
</div>
`,
);
let descriptionAndActionsElement = document.getElementById("top-row");
descriptionAndActionsElement.style.borderBottom = "1px solid var(--yt-spec-10-percent-layer)";
descriptionAndActionsElement.style.paddingBottom = "10px";
} else {
document.querySelector(".ryd-tooltip").style.width = widthPx + "px";
document.getElementById("return-youtube-dislike-bar").style.width = widthPercent + "%";
if (extConfig.coloredBar) {
document.getElementById("return-youtube-dislike-bar-container").style.backgroundColor = getColorFromTheme(false);
document.getElementById("return-youtube-dislike-bar").style.backgroundColor = getColorFromTheme(true);
}
}
}
function setState() {
cLog("Fetching votes...");
let statsSet = false;
fetch(`https://returnyoutubedislikeapi.com/votes?videoId=${getVideoId()}`).then((response) => {
response.json().then((json) => {
if (json && !("traceId" in response) && !statsSet) {
const { dislikes, likes } = json;
cLog(`Received count: ${dislikes}`);
likesvalue = likes;
dislikesvalue = dislikes;
setDislikes(numberFormat(dislikes));
if (extConfig.numberDisplayReformatLikes === true) {
const nativeLikes = getLikeCountFromButton();
if (nativeLikes !== false) {
setLikes(numberFormat(nativeLikes));
}
}
createRateBar(likes, dislikes);
if (extConfig.coloredThumbs === true) {
const dislikeButton = getDislikeButton();
if (isShorts()) {
// for shorts, leave deactived buttons in default color
const shortLikeButton = getLikeButton().querySelector("tp-yt-paper-button#button");
const shortDislikeButton = dislikeButton?.querySelector("tp-yt-paper-button#button");
if (shortLikeButton.getAttribute("aria-pressed") === "true") {
shortLikeButton.style.color = getColorFromTheme(true);
}
if (shortDislikeButton && shortDislikeButton.getAttribute("aria-pressed") === "true") {
shortDislikeButton.style.color = getColorFromTheme(false);
}
shortsObserver.observe(shortLikeButton);
shortsObserver.observe(shortDislikeButton);
} else {
getLikeButton().style.color = getColorFromTheme(true);
if (dislikeButton) dislikeButton.style.color = getColorFromTheme(false);
}
}
}
});
});
}
function updateDOMDislikes() {
setDislikes(numberFormat(dislikesvalue));
createRateBar(likesvalue, dislikesvalue);
}
function likeClicked() {
if (checkForUserAvatarButton() == true) {
if (previousState == 1) {
likesvalue--;
updateDOMDislikes();
previousState = 3;
} else if (previousState == 2) {
likesvalue++;
dislikesvalue--;
updateDOMDislikes();
previousState = 1;
} else if (previousState == 3) {
likesvalue++;
updateDOMDislikes();
previousState = 1;
}
if (extConfig.numberDisplayReformatLikes === true) {
const nativeLikes = getLikeCountFromButton();
if (nativeLikes !== false) {
setLikes(numberFormat(nativeLikes));
}
}
}
}
function dislikeClicked() {
if (checkForUserAvatarButton() == true) {
if (previousState == 3) {
dislikesvalue++;
updateDOMDislikes();
previousState = 2;
} else if (previousState == 2) {
dislikesvalue--;
updateDOMDislikes();
previousState = 3;
} else if (previousState == 1) {
likesvalue--;
dislikesvalue++;
updateDOMDislikes();
previousState = 2;
if (extConfig.numberDisplayReformatLikes === true) {
const nativeLikes = getLikeCountFromButton();
if (nativeLikes !== false) {
setLikes(numberFormat(nativeLikes));
}
}
}
}
}
function setInitialState() {
setState();
}
function getVideoId() {
const urlObject = new URL(window.location.href);
const pathname = urlObject.pathname;
if (pathname.startsWith("/clip")) {
return (document.querySelector("meta[itemprop='videoId']") || document.querySelector("meta[itemprop='identifier']")).content;
} else {
if (pathname.startsWith("/shorts")) {
return pathname.slice(8);
}
return urlObject.searchParams.get("v");
}
}
function isVideoLoaded() {
if (isMobile) {
return document.getElementById("player").getAttribute("loading") == "false";
}
const videoId = getVideoId();
return (
// desktop: spring 2024 UI
document.querySelector(`ytd-watch-grid[video-id='${videoId}']`) !== null ||
// desktop: older UI
document.querySelector(`ytd-watch-flexy[video-id='${videoId}']`) !== null ||
// mobile: no video-id attribute
document.querySelector('#player[loading="false"]:not([hidden])') !== null
);
}
function roundDown(num) {
if (num < 1000) return num;
const int = Math.floor(Math.log10(num) - 2);
const decimal = int + (int % 3 ? 1 : 0);
const value = Math.floor(num / 10 ** decimal);
return value * 10 ** decimal;
}
function numberFormat(numberState) {
let numberDisplay;
if (extConfig.numberDisplayRoundDown === false) {
numberDisplay = numberState;
} else {
numberDisplay = roundDown(numberState);
}
return getNumberFormatter(extConfig.numberDisplayFormat).format(numberDisplay);
}
function getNumberFormatter(optionSelect) {
let userLocales;
if (document.documentElement.lang) {
userLocales = document.documentElement.lang;
} else if (navigator.language) {
userLocales = navigator.language;
} else {
try {
userLocales = new URL(
Array.from(document.querySelectorAll("head > link[rel='search']"))
?.find((n) => n?.getAttribute("href")?.includes("?locale="))
?.getAttribute("href"),
)?.searchParams?.get("locale");
} catch {
cLog("Cannot find browser locale. Use en as default for number formatting.");
userLocales = "en";
}
}
let formatterNotation;
let formatterCompactDisplay;
switch (optionSelect) {
case "compactLong":
formatterNotation = "compact";
formatterCompactDisplay = "long";
break;
case "standard":
formatterNotation = "standard";
formatterCompactDisplay = "short";
break;
case "compactShort":
default:
formatterNotation = "compact";
formatterCompactDisplay = "short";
}
const formatter = Intl.NumberFormat(userLocales, {
notation: formatterNotation,
compactDisplay: formatterCompactDisplay,
});
return formatter;
}
function getColorFromTheme(voteIsLike) {
let colorString;
switch (extConfig.colorTheme) {
case "accessible":
if (voteIsLike === true) {
colorString = "dodgerblue";
} else {
colorString = "gold";
}
break;
case "neon":
if (voteIsLike === true) {
colorString = "aqua";
} else {
colorString = "magenta";
}
break;
case "classic":
default:
if (voteIsLike === true) {
colorString = "lime";
} else {
colorString = "red";
}
}
return colorString;
}
let smartimationObserver = null;
function setEventListeners(evt) {
let jsInitChecktimer;
function checkForJS_Finish() {
//console.log();
if (isShorts() || (getButtons()?.offsetParent && isVideoLoaded())) {
const buttons = getButtons();
const dislikeButton = getDislikeButton();
if (preNavigateLikeButton !== getLikeButton() && dislikeButton) {
cLog("Registering button listeners...");
try {
getLikeButton().addEventListener("click", likeClicked);
dislikeButton?.addEventListener("click", dislikeClicked);
getLikeButton().addEventListener("touchstart", likeClicked);
dislikeButton?.addEventListener("touchstart", dislikeClicked);
dislikeButton?.addEventListener("focusin", updateDOMDislikes);
dislikeButton?.addEventListener("focusout", updateDOMDislikes);
preNavigateLikeButton = getLikeButton();
if (!smartimationObserver) {
smartimationObserver = createObserver(
{
attributes: true,
subtree: true,
childList: true,
},
updateDOMDislikes,
);
smartimationObserver.container = null;
}
const smartimationContainer = buttons.querySelector("yt-smartimation");
if (smartimationContainer && smartimationObserver.container != smartimationContainer) {
cLog("Initializing smartimation mutation observer");
smartimationObserver.disconnect();
smartimationObserver.observe(smartimationContainer);
smartimationObserver.container = smartimationContainer;
}
} catch {
return;
} //Don't spam errors into the console
}
if (dislikeButton) {
setInitialState();
clearInterval(jsInitChecktimer);
}
}
}
cLog("Setting up...");
jsInitChecktimer = setInterval(checkForJS_Finish, 111);
}
(function () {
"use strict";
window.addEventListener("yt-navigate-finish", setEventListeners, true);
setEventListeners();
})();
if (isMobile) {
let originalPush = history.pushState;
history.pushState = function (...args) {
window.returnDislikeButtonlistenersSet = false;
setEventListeners(args[2]);
return originalPush.apply(history, args);
};
setInterval(() => {
const dislikeButton = getDislikeButton();
if (dislikeButton?.querySelector(".button-renderer-text") === null) {
getDislikeTextContainer().innerText = mobileDislikes;
} else {
if (dislikeButton) dislikeButton.querySelector(".button-renderer-text").innerText = mobileDislikes;
}
}, 1000);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,18 @@
// ==UserScript==
// @name Startpage - Hide Ads
// @match https://www.startpage.com/*
// @run-at document-start
// ==/UserScript==
new MutationObserver(function(mutations) {
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1 && node.nodeName === 'DIV' && node.id === 'gcsa-top') {
node.remove();
this.disconnect();
}
});
}
});
}).observe(document, { childList: true, subtree: true });
@@ -0,0 +1,191 @@
// ==UserScript==
// @name TrackingTokenStripper
// @version 1.4
// @description Remove most of the annoying tracking token from URL parameters
// @license MIT
// @homepage https://blog.miniasp.com/
// @homepageURL https://blog.miniasp.com/
// @website https://www.facebook.com/will.fans
// @source https://github.com/doggy8088/TrackingTokenStripper/raw/refs/heads/master/TrackingTokenStripper.user.js
// @namespace https://github.com/doggy8088/TrackingTokenStripper
// @author Will Huang
// @match *://*/*
// @run-at document-start
// ==/UserScript==
(function () {
'use strict';
const oldReplaceState = history.replaceState;
history.replaceState = function replaceState() {
let ret = oldReplaceState.apply(this, arguments);
window.dispatchEvent(new Event('replacestate'));
window.dispatchEvent(new Event('locationchange'));
return ret;
};
window.addEventListener('popstate', () => {
window.dispatchEvent(new Event('locationchange'));
});
window.addEventListener('locationchange', function () {
executeActions();
});
executeActions();
let id = setInterval(executeActions, 500);
setTimeout(() => { clearInterval(id); }, 2000);
function executeActions() {
var s = TrackingTokenStripper(location.href)
// facebook
.remove('fbclid')
.removeByDomain('www.facebook.com', 'privacy_mutation_token')
.removeByDomain('www.facebook.com', 'acontext')
.removeByDomain('www.facebook.com', '__xts__[0]')
.removeByDomain('www.facebook.com', 'notif_t')
.removeByDomain('www.facebook.com', 'notif_id')
.removeByDomain('www.facebook.com', 'notif_ids[0]')
.removeByDomain('www.facebook.com', 'notif_ids[1]')
.removeByDomain('www.facebook.com', 'notif_ids[2]')
.removeByDomain('www.facebook.com', 'notif_ids[3]')
.removeByDomain('www.facebook.com', 'ref', 'notif')
.removeByDomain('www.facebook.com', 'ref=watch_permalink')
// Dropbox
.removeByDomain('www.dropbox.com', '_ad')
.removeByDomain('www.dropbox.com', '_camp')
.removeByDomain('www.dropbox.com', '_tk')
// YouTube
// https://youtu.be/4f-Y9G5ENPc?si=SHSu2hEdSbXGy4_Q
// https://www.youtube.com/embed/4f-Y9G5ENPc?si=GQFJV_nKMXxpiQb6
.removeByDomain('youtu.be', 'si')
.removeByDomain('www.youtube.com', 'si')
// Google Analytics
// https://support.google.com/analytics/answer/1033863?hl=en
.remove('utm_id')
.remove('utm_source')
.remove('utm_medium')
.remove('utm_campaign')
.remove('utm_term')
.remove('utm_content')
.remove('_ga')
// GA - others
.remove('utm_campaignid')
.remove('utm_cid')
.remove('utm_reader')
.remove('utm_referrer')
.remove('utm_name')
.remove('utm_social')
.remove('utm_social-type')
.remove('gclid')
.remove('igshid')
.remove('_hsenc')
.remove('_hsmi')
.remove('mc_cid')
.remove('mc_eid')
.remove('mkt_tok')
.remove('yclid')
.remove('_openstat')
// devblogs.microsoft.com
.removeByDomain('devblogs.microsoft.com', 'utm_issue')
.removeByDomain('devblogs.microsoft.com', 'utm_position')
.removeByDomain('devblogs.microsoft.com', 'utm_topic')
.removeByDomain('devblogs.microsoft.com', 'utm_section')
.removeByDomain('devblogs.microsoft.com', 'utm_cta')
.removeByDomain('devblogs.microsoft.com', 'utm_description')
.removeByDomain('devblogs.microsoft.com', 'ocid')
// Microsoft
.remove('wt.mc_id')
.removeByDomain('learn.microsoft.com', 'ocid')
.removeByDomain('learn.microsoft.com', 'redirectedfrom')
.removeByDomain('azure.microsoft.com', 'OCID')
.removeByDomain('azure.microsoft.com', 'ef_id')
.removeByDomain('www.msn.com', 'ocid')
.removeByDomain('www.msn.com', 'cvid')
// bilibili
.removeByDomain('www.bilibili.com', 'share_source')
.removeByDomain('www.bilibili.com', 'share_medium')
// Others
.remove('__tn__')
.remove('gclsrc')
.remove('itm_source')
.remove('itm_medium')
.remove('itm_campaign')
.remove('mc') // sendgrid.com
.remove('mcd') // sendgrid.com
.remove('cvosrc') // sendgrid.com
.remove('cr_cc') // https://blogs.microsoft.com/
.remove('sc_channel')
.remove('sc_campaign')
.remove('sc_geo')
.remove('trk')
.remove('sc_publisher')
.remove('trkCampaign')
.remove('sc_outcome')
.remove('sc_country')
.remove('__hstc')
.remove('__hssc')
.remove('__hsfp')
.remove('_gl')
// Yahoo News
.remove('guce_referrer')
.remove('guce_referrer_sig')
.toString();
if (s && location.href !== s) {
// console.log('Changing URL', s);
// location.href = s;
oldReplaceState.apply(history, [{}, '', s]);
}
function TrackingTokenStripper(url) {
const parsedUrl = new URL(url);
return {
remove(name, value) {
if (parsedUrl.searchParams.has(name)) {
if (value && value === parsedUrl.searchParams.get(name)) {
parsedUrl.searchParams.delete(name);
}
if (!value) {
parsedUrl.searchParams.delete(name);
}
}
return TrackingTokenStripper(parsedUrl.toString());
},
removeByDomain(domain, name) {
if (parsedUrl.hostname.toLocaleLowerCase() === domain.toLocaleLowerCase()) {
if (name.indexOf('=') >= 0) {
var [key, value] = name.split("=");
return this.remove(key, value);
} else {
return this.remove(name);
}
} else {
return this;
}
},
toString() {
return parsedUrl.toString();
}
}
}
}
})();