您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically rejects cookies and legitimate interest
当前为
// ==UserScript== // @name Reject cookie banners // @namespace http://tampermonkey.net/ // @version 1.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 = [ // common { // reject consent and reject legitimate interest // follows GPC 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$/ }, { // more options, reject all, click legitimate interest then object all, save // follows GPC 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$/ }, { // only accept necessary cookies // stackexchange sites banner: 'body > #onetrust-consent-sdk', btn: '[aria-label="Cookie banner"] #onetrust-reject-all-handler' }, { // LEARN MORE, Show Preferences, change all checked checkboxes to not checked, SAVE AND CLOSE // fandom // you need to actually need to scroll down the page for preferences to be changed // hence the while loop 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', htmlMatch: /(^$|.)/, queryAll: true, onToggleFound: function(toggle, cookieNotice, toggleItemNo) { while (toggle.checked) { toggle.click(); } }} ], confirm: 'div[data-tracking-opt-in-save]', confirm_htmlMatch: /^Save And Close$/ }, // linuxy // U { // manage settings, make sure all inputs are not checked banner: 'body > dialog.cookie-policy[open="true"]', btn: '#cookie-policy-content button', btn_htmlMatch: /^Manage your tracker settings$/, toggles: '#controls input[type="checkbox"]:checked', confirm: 'button', confirm_htmlMatch: /^Save preferences$/ }, // news // B { // reject additional cookies banner: 'section[aria-labelledby="consent-banner-title"]', btn: 'div[class*="Options"] button', btn_htmlMatch: /^Reject additional cookies$/ }, // weather // M { // (starts on How data is used) make sure cookies are rejected and disable legitimate interest, Save Preferences and Exit // no need to click Third party vendors because they correctly recognise legitimate interest rejected banner: 'body > div#ccc[aria-label="Cookie preferences"]', toggles: [ {query: 'input[type="checkbox"]:checked', htmlMatch: /(^$|.)/, queryAll: true} ], confirm: 'button#ccc-dismiss-button span', confirm_htmlMatch: /^Save Preferences and Exit$/ }, // N { // 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' }, // free to watch ad-supported video streaming services // 4, U { // Manage, make sure all are off (they default too off anyway) banner: 'body > #cookie-consent-banner', btn: 'button[aria-label="Manage which purposes to accept cookies for."]', toggles: [ {query: '[class$="cc-popup-absolute"] > [class$="__component"] > [class$="__header"] + [class*="__content-area"] > [class$="cc-accordion-container"] [class$="cc-accordion-item--header"] [role="switch"][aria-checked="true"]', htmlMatch: /(^$|.)/, queryAll: true} ], confirm: 'button[aria-label="Save cookie preferences and continue"]' }, // uk supermarkets // T { // reject all. the Show purposes button does nothing, neither does the List of vendors banner: 'body div[data-mfe="mfe-header"] div[class*="mfe-header"]', btn: 'div[class*="consent-banner__buttons-container"] button', btn_htmlMatch: /[>]\s*Reject all<\/span>$/ }, { // Manage Cookies - this opens __tealiumGDPRcpPrefs banner: 'body > #__tealiumGDPRecModal:has(.privacy_prompt_fadeout + .privacy_prompt_centre .privacy_prompt_footer)', btn: '#privacy-more-information.button', btn_htmlMatch: /[>]\s*Manage Cookies<\/span>\s*$/ }, { // make sure all are off then Save preferences banner: 'body > #__tealiumGDPRcpPrefs:has(.privacy_prompt_fadeout + .categories_centre .consent_preferences .privacy_prompt_content)', toggles: '.table-wrapper table tr input.toggle[type="checkbox"]:checked', confirm: '#preferences_prompt_submit.button', confirm_htmlMatch: /[>]\s*Save preferences<\/span>\s*$/ } ]; // if same banner seen more than once, remove the banner instead of clicking buttons let timesSeenSameBanners = {}; 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 fakeBtn = {click: function() {}}; if (!cookieNotice.btn) { return fakeBtn; } const banner = getBanner(cookieNotice); if (!banner) { // somehow happens on at least one site where the banner suddenly disappears // possibly due to cursor or touch or resize events which change the DOM return fakeBtn; } 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); for (const toggle of toggles) { if (toggle.innerHTML.match(toggleItem.htmlMatch)) { if (typeof toggleItem.onToggleFound === 'function') { await toggleItem.onToggleFound(toggle, cookieNotice, toggleItemNo); } else { 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; } if (!timesSeenSameBanners[cookieNotice.banner]) { timesSeenSameBanners[cookieNotice.banner] = 0; } if (timesSeenSameBanners[cookieNotice.banner] > 1) { // clicking buttons can cause cookie notice to appear again // in that case remove the banner without clicking buttons getBanner(cookieNotice).remove(); 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 const banner = getBanner(cookieNotice); if (banner) { // banner might be removed after clicking button banner.outerHTML = ''; } } timesSeenSameBanners[cookieNotice.banner]++; } function rejectAll() { for (let i = 0; i < rejections.length; i++) { tryRejecting(rejections[i], true); } // cookie banner may not have been created yet, try again setTimeout(rejectAll, 200); } rejectAll(); })();