// ==UserScript==
// @name Reject cookie banners
// @namespace http://tampermonkey.net/
// @version 1.3.3.6
// @description Automatically rejects cookies and legitimate interest
// @author https://greasyfork.org/en/users/85040-dan-wl-danwl
// @license MIT
// @match *://*/*
// @run-at document-start
// @grant none
// ==/UserScript==
// MIT License
// Copyright(c) 2024 DanWL
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
(function() {
const rejections = [
{
// reject consent and reject legitimate interest
banner: 'body > .fc-consent-root',
btn: 'button[aria-label^="Manage"] > p',
btn_htmlMatch: /^Manage options$/,
toggles: '.fc-preference-slider input[aria-label^="Consent"]:checked, .fc-preference-slider input[aria-label^="Legitimate interest"]:checked',
confirm: 'button[aria-label^="Confirm"] p',
confirm_htmlMatch: /^Confirm choices$/
},
{
// only accept necessary cookies
banner: 'body > #onetrust-consent-sdk',
btn: '[aria-label="Cookie banner"] #onetrust-reject-all-handler'
},
{
// click customize and reject all
banner: 'body > .cmpwrapper',
btn: 'div#cmpbox > div.cmpboxinner > div.cmpboxbtns > div.cmpmore > a.cmpmorelink.cmptxt_btn_custom',
toggles: null,
confirm: 'div#cmpbox > div.cmpboxinner > div.cmpboxbtnscustomchoices > a.cmpboxbtn.cmpboxbtnreject.cmpboxbtnrejectcustomchoices.cmptxt_btn_no'
},
{
// more options, reject all, click legitimate interest then object all, save
banner: 'body > .qc-cmp2-container',
btn: '.qc-cmp2-summary-buttons > button[mode="secondary"][size="large"] > span',
btn_htmlMatch: /^MORE OPTIONS$/,
toggles: [
{query: '.qc-cmp2-header-links > button[mode="link"][size="small"]', htmlMatch: /^REJECT ALL$/},
{query: '.qc-cmp2-footer-links > button[mode="link"][size="small"]', htmlMatch: /^LEGITIMATE INTEREST$/},
{query: '.qc-cmp2-header-links > button[mode="link"][size="small"]', htmlMatch: /^OBJECT ALL$/}
],
confirm: '.qc-cmp2-footer-links + .qc-cmp2-buttons-desktop button[mode="primary"][size="large"]',
confirm_htmlMatch: /^SAVE & EXIT$/
},
{
// LEARN MORE, Show Preferences, click all checked checkboxes, (save TODO)
banner: 'body > div:has(div[data-tracking-opt-in-overlay])',
btn: 'div[data-tracking-opt-in-learn-more]',
btn_htmlMatch: /^LEARN MORE$/,
toggles: [
{query: 'div[class]', htmlMatch: /^\s*Show Preferences\s*<svg\s+/, queryAll: true},
{query: 'input[id^="switch"][type="checkbox"]:checked + label[for^=switch]', htmlMatch: /^$/, queryAll: true},
],
DONT_CLOSE: true
}
];
let dealtWithBanner = false;
function sleep(ms) {
// cookie banner not fully loaded when trying to select elements
// so wait for a bit until it has
return new Promise((resolve) => {
setTimeout(() => resolve(), ms);
})
}
function getBanner(cookieNotice) {
return document.querySelector(cookieNotice.banner);
}
async function getBtn(cookieNotice) {
const banner = getBanner(cookieNotice);
if (cookieNotice.btn_htmlMatch) {
const btns = (banner.shadowRoot || banner).querySelectorAll(cookieNotice.btn);
for (const btn of btns) {
if (btn.innerHTML.match(cookieNotice.btn_htmlMatch)) {
return btn;
}
}
}
else {
const btn = (banner.shadowRoot || banner).querySelector(cookieNotice.btn);
if (btn) {
return btn;
}
}
// if made it down to here then btn does not exist, so wait and try again
await sleep(10);
return await getBtn(cookieNotice);
}
async function clickToggle(cookieNotice, toggleItemNo) {
if (toggleItemNo >= cookieNotice.toggles.length) {
return;
}
const toggleItem = cookieNotice.toggles[toggleItemNo];
let banner = getBanner(cookieNotice);
if (toggleItem.htmlMatch) {
if (toggleItem.queryAll) {
// forcefully wait for the cookie notice to load
await sleep(2000);
banner = getBanner(cookieNotice);
}
const toggles = (banner.shadowRoot || banner).querySelectorAll(toggleItem.query);
if (!toggles.length) {
const prev = toggleItemNo > 0 ? 1 : 0;
return await clickToggle(cookieNotice, toggleItemNo - prev);
}
for (const toggle of toggles) {
if (toggle.innerHTML.match(toggleItem.htmlMatch)) {
toggle.click();
if (!toggleItem.queryAll) {
break;
}
}
}
return await clickToggle(cookieNotice, toggleItemNo + 1);
}
else {
const toggle = (banner.shadowRoot || banner).querySelector(toggleItem.query);
if (toggle) {
toggle.click();
return await clickToggle(cookieNotice, toggleItemNo + 1);
}
}
// if made it down to here then toggle does not exist, so wait then try again
await sleep(10);
await clickToggle(cookieNotice, toggleItemNo);
}
async function getConfirmBtn(cookieNotice) {
const banner = getBanner(cookieNotice);
if (cookieNotice.confirm_htmlMatch) {
const btns = (banner.shadowRoot || banner).querySelectorAll(cookieNotice.confirm);
for (const btn of btns) {
if (btn.innerHTML.match(cookieNotice.confirm_htmlMatch)) {
return btn;
}
}
}
else {
const btn = (banner.shadowRoot || banner).querySelector(cookieNotice.confirm);
if (btn) {
return btn;
}
}
if (typeof cookieNotice.toggles === 'string') {
// confirm button not loaded to go back and make sure that all toggles have been disabled
clickToggle(cookieNotice, 0);
}
// if made it down to here then it does not exist, so wait then try again
await sleep(10);
return await getConfirmBtn(cookieNotice);
}
async function tryRejecting(cookieNotice) {
if (!getBanner(cookieNotice)) {
return;
}
const btn = await getBtn(cookieNotice);
const togglesIsString = typeof cookieNotice.toggles == 'string';
const togglesIsArray = Array.isArray(cookieNotice.toggles);
if (cookieNotice.toggles === null || togglesIsString || togglesIsArray) {
btn.click();
if (togglesIsString) {
// if toggles arent loaded by the time the confirm button exists, toggles will be disabled
const banner = getBanner(cookieNotice);
(banner.shadowRoot || banner).querySelectorAll(cookieNotice.toggles).forEach(function(toggle) {
toggle.click();
});
}
else if (togglesIsArray) {
// clicks all toggles in the exact order they appear in
// for buttons like 'reject all' or 'object all' when they are actually provided
await clickToggle(cookieNotice, 0);
}
if (cookieNotice.DONT_CLOSE) {
return;
}
(await getConfirmBtn(cookieNotice)).click();
}
else {
// some pages would constantly reload because of automatically clearing and rejecting cookies
// so check if cookies are stored before trying to reject them
if (document.cookie) {
// reject cookies
btn.click();
}
if (cookieNotice.DONT_CLOSE) {
return;
}
// make sure there is no persistent banner
getBanner(cookieNotice).outerHTML = '';
}
dealtWithBanner = true;
}
function rejectAll() {
for (let i = 0; i < rejections.length; i++) {
tryRejecting(rejections[i], true);
}
if (dealtWithBanner) {
return;
}
// cookie banner may not have been created yet, try again
setTimeout(rejectAll, 200);
}
rejectAll();
})();