@duckduckgo/autoconsent 2.1.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/.idea/.vscode.iml +9 -0
- package/.vscode/.idea/modules.xml +8 -0
- package/.vscode/.idea/workspace.xml +28 -0
- package/.vscode/settings.json +7 -0
- package/dist/addon-firefox/background.bundle.js +1 -1
- package/dist/addon-firefox/content.bundle.js +1 -1
- package/dist/addon-firefox/manifest.json +1 -1
- package/dist/addon-firefox/rules.json +821 -48
- package/dist/addon-mv3/background.bundle.js +1 -1
- package/dist/addon-mv3/content.bundle.js +1 -1
- package/dist/addon-mv3/manifest.json +1 -1
- package/dist/addon-mv3/rules.json +821 -48
- package/dist/autoconsent.cjs.js +1 -1
- package/dist/autoconsent.esm.js +1 -1
- package/dist/autoconsent.playwright.js +1 -1
- package/lib/cmps/all.ts +7 -0
- package/lib/cmps/base.ts +37 -24
- package/lib/cmps/consentmanager.ts +27 -4
- package/lib/cmps/conversant.ts +60 -0
- package/lib/cmps/klaro.ts +66 -0
- package/lib/cmps/sourcepoint-frame.ts +9 -8
- package/lib/cmps/sourcepoint-top.ts +5 -0
- package/lib/cmps/uniconsent.ts +70 -0
- package/lib/rules.ts +8 -1
- package/lib/web.ts +35 -25
- package/package.json +1 -1
- package/readme.md +29 -0
- package/rules/autoconsent/adroll.json +11 -0
- package/rules/autoconsent/aws-amazon.json +6 -1
- package/rules/autoconsent/axeptio.json +41 -0
- package/rules/autoconsent/clickio.json +18 -0
- package/rules/autoconsent/complianz-banner.json +13 -0
- package/rules/autoconsent/complianz-categories.json +17 -0
- package/rules/autoconsent/complianz-notice.json +14 -0
- package/rules/autoconsent/complianz-optin.json +20 -0
- package/rules/autoconsent/cookie-notice.json +3 -1
- package/rules/autoconsent/cookieinformation.json +14 -0
- package/rules/autoconsent/dsgvo.json +16 -0
- package/rules/autoconsent/eu-cookie-law.json +20 -0
- package/rules/autoconsent/ezoic.json +19 -0
- package/rules/autoconsent/iubenda.json +23 -0
- package/rules/autoconsent/jquery-cookiebar.json +25 -0
- package/rules/autoconsent/mediavine.json +20 -0
- package/rules/autoconsent/moove.json +28 -0
- package/rules/autoconsent/paypal.json +4 -1
- package/rules/autoconsent/primebox.json +19 -0
- package/rules/autoconsent/sirdata.json +11 -0
- package/rules/autoconsent/tarteaucitron.json +18 -0
- package/rules/autoconsent/tealium.json +0 -1
- package/rules/autoconsent/termly.json +31 -0
- package/rules/autoconsent/testcmp.json +4 -1
- package/rules/autoconsent/uk-cookie-consent.json +15 -0
- package/rules/autoconsent/{usercentrics-1.json → usercentrics-api.json} +2 -2
- package/rules/autoconsent/usercentrics-button.json +14 -0
- package/rules/autoconsent/vodafone-de.json +5 -5
- package/rules/autoconsent/wp-cookie-notice.json +12 -0
- package/rules/rules.json +821 -48
- package/tests/adroll.spec.ts +15 -0
- package/tests/axeptio.spec.ts +9 -0
- package/tests/clickio.spec.ts +10 -0
- package/tests/complianz-banner.spec.ts +9 -0
- package/tests/complianz-categories.spec.ts +14 -0
- package/tests/{cookieconsent.spec.ts → complianz-notice.spec.ts} +1 -2
- package/tests/complianz-optin.spec.ts +6 -0
- package/tests/consentmanager.spec.ts +2 -1
- package/tests/conversant.spec.ts +10 -0
- package/tests/{cookienotice.spec.ts → cookie-notice.spec.ts} +0 -0
- package/tests/cookieinformation.spec.ts +10 -0
- package/tests/dsgvo.spec.ts +6 -0
- package/tests/eu-cookie-law.spec.ts +6 -0
- package/tests/ezoic.spec.ts +8 -0
- package/tests/iubenda.spec.ts +8 -0
- package/tests/jquery-cookiebar.spec.ts +6 -0
- package/tests/klaro.spec.ts +6 -2
- package/tests/mediavine.spec.ts +8 -0
- package/tests/moove.spec.ts +13 -0
- package/tests/onetrust.spec.ts +2 -2
- package/tests/primebox.spec.ts +7 -0
- package/tests/sirdata.spec.ts +8 -0
- package/tests/tarteaucitron.spec.ts +9 -0
- package/tests/tealium.spec.ts +1 -1
- package/tests/termly.spec.ts +12 -0
- package/tests/trustarc.spec.ts +1 -9
- package/tests/uk-cookie-consent.spec.ts +7 -0
- package/tests/uniconsent.spec.ts +12 -0
- package/tests/{usercentrics-1.spec.ts → usercentrics-api.spec.ts} +3 -2
- package/tests/usercentrics-button.spec.ts +8 -0
- package/tests/wp-cookie-notice.spec.ts +8 -0
- package/dist/autoconsent.standalone.js +0 -1
- package/rules/autoconsent/cookieconsent.json +0 -8
- package/rules/autoconsent/destatis-de.json +0 -8
- package/rules/autoconsent/klaro.json +0 -10
- package/tests/destatis.spec.ts +0 -7
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { click, elementExists, elementVisible, waitForElement } from "../rule-executors";
|
|
1
|
+
import { click, doEval, elementExists, elementVisible, wait, waitForElement } from "../rule-executors";
|
|
2
2
|
import AutoConsentCMPBase from "./base";
|
|
3
3
|
|
|
4
4
|
// Note: JS API is also available:
|
|
5
5
|
// https://help.consentmanager.net/books/cmp/page/javascript-api
|
|
6
6
|
export default class ConsentManager extends AutoConsentCMPBase {
|
|
7
7
|
|
|
8
|
-
prehideSelectors = ["#cmpbox,#cmpbox2"]
|
|
8
|
+
prehideSelectors = ["#cmpbox,#cmpbox2"];
|
|
9
|
+
apiAvailable = false;
|
|
9
10
|
|
|
10
11
|
get hasSelfTest(): boolean {
|
|
11
|
-
return
|
|
12
|
+
return this.apiAvailable;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
get isIntermediate(): boolean {
|
|
@@ -20,14 +21,27 @@ export default class ConsentManager extends AutoConsentCMPBase {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
async detectCmp() {
|
|
23
|
-
|
|
24
|
+
this.apiAvailable = await doEval('window.__cmp && typeof __cmp("getCMPData") === "object"');
|
|
25
|
+
if (!this.apiAvailable) {
|
|
26
|
+
return elementExists("#cmpbox");
|
|
27
|
+
} else {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
24
30
|
}
|
|
25
31
|
|
|
26
32
|
async detectPopup() {
|
|
33
|
+
if (this.apiAvailable) {
|
|
34
|
+
return await doEval("!__cmp('consentStatus').userChoiceExists");
|
|
35
|
+
}
|
|
27
36
|
return elementVisible("#cmpbox .cmpmore", 'any');
|
|
28
37
|
}
|
|
29
38
|
|
|
30
39
|
async optOut() {
|
|
40
|
+
await wait(500);
|
|
41
|
+
if (this.apiAvailable) {
|
|
42
|
+
return await doEval("__cmp('setConsent', 0)");
|
|
43
|
+
}
|
|
44
|
+
|
|
31
45
|
if (click(".cmpboxbtnno")) {
|
|
32
46
|
return true;
|
|
33
47
|
}
|
|
@@ -46,6 +60,15 @@ export default class ConsentManager extends AutoConsentCMPBase {
|
|
|
46
60
|
}
|
|
47
61
|
|
|
48
62
|
async optIn() {
|
|
63
|
+
if (this.apiAvailable) {
|
|
64
|
+
return await doEval("__cmp('setConsent', 1)");
|
|
65
|
+
}
|
|
49
66
|
return click(".cmpboxbtnyes");
|
|
50
67
|
}
|
|
68
|
+
|
|
69
|
+
async test() {
|
|
70
|
+
if (this.apiAvailable) {
|
|
71
|
+
return await doEval("__cmp('consentStatus').userChoiceExists");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
51
74
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { click, elementExists, elementVisible, waitForElement, waitForThenClick } from "../rule-executors";
|
|
2
|
+
import { waitFor } from "../utils";
|
|
3
|
+
import AutoConsentCMPBase from "./base";
|
|
4
|
+
|
|
5
|
+
export default class Conversant extends AutoConsentCMPBase {
|
|
6
|
+
|
|
7
|
+
prehideSelectors = [".cmp-root"]
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
super("Conversant");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get hasSelfTest(): boolean {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get isIntermediate(): boolean {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async detectCmp() {
|
|
22
|
+
return elementExists(".cmp-root .cmp-receptacle");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async detectPopup() {
|
|
26
|
+
return elementVisible(".cmp-root .cmp-receptacle", 'any');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async optOut() {
|
|
30
|
+
if (!(await waitForThenClick(".cmp-main-button:not(.cmp-main-button--primary)"))) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (!(await waitForElement(".cmp-view-tab-tabs"))) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
await waitForThenClick(".cmp-view-tab-tabs > :first-child");
|
|
39
|
+
await waitForThenClick(".cmp-view-tab-tabs > .cmp-view-tab--active:first-child");
|
|
40
|
+
|
|
41
|
+
for (const item of Array.from(document.querySelectorAll('.cmp-accordion-item'))) {
|
|
42
|
+
(<HTMLElement>item.querySelector('.cmp-accordion-item-title')).click();
|
|
43
|
+
await waitFor(() => !!item.querySelector('.cmp-accordion-item-content.cmp-active'), 10, 50);
|
|
44
|
+
const content = item.querySelector('.cmp-accordion-item-content.cmp-active');
|
|
45
|
+
content.querySelectorAll('.cmp-toggle-actions .cmp-toggle-deny:not(.cmp-toggle-deny--active)').forEach((e: HTMLElement) => e.click());
|
|
46
|
+
content.querySelectorAll('.cmp-toggle-actions .cmp-toggle-checkbox:not(.cmp-toggle-checkbox--active)').forEach((e: HTMLElement) => e.click());
|
|
47
|
+
// await waitFor(() => !item.querySelector('.cmp-toggle-deny--active,.cmp-toggle-checkbox--active'), 5, 50); // this may take a long time
|
|
48
|
+
}
|
|
49
|
+
await click(".cmp-main-button:not(.cmp-main-button--primary)");
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async optIn() {
|
|
54
|
+
return waitForThenClick(".cmp-main-button.cmp-main-button--primary");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async test() {
|
|
58
|
+
return document.cookie.includes('cmp-data=0');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { click, doEval, elementExists, elementVisible, waitForElement } from "../rule-executors";
|
|
2
|
+
import AutoConsentCMPBase from "./base";
|
|
3
|
+
|
|
4
|
+
export default class Klaro extends AutoConsentCMPBase {
|
|
5
|
+
|
|
6
|
+
prehideSelectors = [".klaro"]
|
|
7
|
+
settingsOpen = false;
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
super("Klaro");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get hasSelfTest(): boolean {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get isIntermediate(): boolean {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async detectCmp() {
|
|
22
|
+
if (elementExists('.klaro > .cookie-modal')) {
|
|
23
|
+
this.settingsOpen = true;
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
return elementExists(".klaro > .cookie-notice");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async detectPopup() {
|
|
30
|
+
return elementVisible(".klaro > .cookie-notice,.klaro > .cookie-modal", 'any');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async optOut() {
|
|
34
|
+
if (click('.klaro .cn-decline')) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!this.settingsOpen) {
|
|
39
|
+
click('.klaro .cn-learn-more');
|
|
40
|
+
await waitForElement('.klaro > .cookie-modal', 2000);
|
|
41
|
+
this.settingsOpen = true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (click('.klaro .cn-decline')) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
click('.cm-purpose:not(.cm-toggle-all) > input:not(.half-checked)', true);
|
|
49
|
+
return click('.cm-btn-accept');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async optIn() {
|
|
53
|
+
if (click('.klaro .cm-btn-accept-all')) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
if (this.settingsOpen) {
|
|
57
|
+
click('.cm-purpose:not(.cm-toggle-all) > input.half-checked', true);
|
|
58
|
+
return click('.cm-btn-accept');
|
|
59
|
+
}
|
|
60
|
+
return click('.klaro .cookie-notice .cm-btn-success');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async test() {
|
|
64
|
+
return await doEval('klaro.getManager().config.services.every(c => c.required || !klaro.getManager().consents[c.name])');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -32,7 +32,7 @@ export default class SourcePoint extends AutoConsentCMPBase {
|
|
|
32
32
|
return true;
|
|
33
33
|
}
|
|
34
34
|
return (url.pathname === '/index.html' || url.pathname === '/privacy-manager/index.html')
|
|
35
|
-
&& url.searchParams.has('message_id')
|
|
35
|
+
&& (url.searchParams.has('message_id') || url.searchParams.has('requestUUID') || url.searchParams.has('consentUUID'));
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
async detectPopup() {
|
|
@@ -57,16 +57,17 @@ export default class SourcePoint extends AutoConsentCMPBase {
|
|
|
57
57
|
|
|
58
58
|
async optOut() {
|
|
59
59
|
if (!this.isManagerOpen()) {
|
|
60
|
-
const actionable = await waitForElement('
|
|
60
|
+
const actionable = await waitForElement('.sp_choice_type_12,.sp_choice_type_13');
|
|
61
61
|
if (!actionable) {
|
|
62
62
|
return false;
|
|
63
63
|
}
|
|
64
|
-
if (!elementExists("
|
|
64
|
+
if (!elementExists(".sp_choice_type_12")) {
|
|
65
65
|
// do not sell button
|
|
66
|
-
return click("
|
|
66
|
+
return click(".sp_choice_type_13");
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
click("
|
|
69
|
+
click(".sp_choice_type_12");
|
|
70
|
+
// the page may navigate at this point but that's okay
|
|
70
71
|
await waitFor(
|
|
71
72
|
() => location.pathname === "/privacy-manager/index.html",
|
|
72
73
|
200,
|
|
@@ -88,9 +89,8 @@ export default class SourcePoint extends AutoConsentCMPBase {
|
|
|
88
89
|
await wait(1000);
|
|
89
90
|
return click(rejectSelector1);
|
|
90
91
|
} else if (path === 1) {
|
|
91
|
-
|
|
92
|
+
click(rejectSelector2);
|
|
92
93
|
} else if (path === 2) {
|
|
93
|
-
// TODO: check if this is still working
|
|
94
94
|
await waitForElement('.pm-features', 10000);
|
|
95
95
|
click('.checked > span', true);
|
|
96
96
|
|
|
@@ -99,6 +99,7 @@ export default class SourcePoint extends AutoConsentCMPBase {
|
|
|
99
99
|
} catch (e) {
|
|
100
100
|
enableLogs && console.warn(e);
|
|
101
101
|
}
|
|
102
|
-
|
|
102
|
+
click('.sp_choice_type_SAVE_AND_EXIT');
|
|
103
|
+
return true;
|
|
103
104
|
}
|
|
104
105
|
}
|
|
@@ -35,6 +35,11 @@ export default class SourcePoint extends AutoConsentCMPBase {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
async optOut() {
|
|
38
|
+
// unblock scrolling
|
|
39
|
+
const container = document.querySelector('.sp-message-open');
|
|
40
|
+
if (container) {
|
|
41
|
+
container.classList.remove('sp-message-open');
|
|
42
|
+
}
|
|
38
43
|
return true;
|
|
39
44
|
}
|
|
40
45
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { elementExists, elementVisible, wait, waitForElement, waitForThenClick } from "../rule-executors";
|
|
2
|
+
import AutoConsentCMPBase from "./base";
|
|
3
|
+
|
|
4
|
+
export default class Uniconsent extends AutoConsentCMPBase {
|
|
5
|
+
constructor() {
|
|
6
|
+
super("Uniconsent");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
get prehideSelectors(): string[] {
|
|
10
|
+
return ['.unic'];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get hasSelfTest(): boolean {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get isIntermediate(): boolean {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async detectCmp() {
|
|
22
|
+
return elementExists(".unic .unic-box,.unic .unic-bar");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async detectPopup() {
|
|
26
|
+
return elementVisible(".unic .unic-box,.unic .unic-bar", 'any');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async optOut() {
|
|
30
|
+
await waitForElement(".unic button", 1000);
|
|
31
|
+
document.querySelectorAll(".unic button").forEach((button: HTMLButtonElement) => {
|
|
32
|
+
const text = button.textContent;
|
|
33
|
+
if (text.includes('Manage Options') || text.includes('Optionen verwalten')) {
|
|
34
|
+
button.click();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
if (await waitForElement('.unic input[type=checkbox]', 1000)) {
|
|
39
|
+
await waitForElement('.unic button', 1000);
|
|
40
|
+
|
|
41
|
+
document.querySelectorAll('.unic input[type=checkbox]').forEach((c: HTMLInputElement) => {
|
|
42
|
+
if (c.checked) {
|
|
43
|
+
c.click();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
for (const b of <NodeListOf<HTMLButtonElement>>document.querySelectorAll('.unic button')) {
|
|
48
|
+
const text = b.textContent;
|
|
49
|
+
for (const pattern of ['Confirm Choices', 'Save Choices', 'Auswahl speichern']) {
|
|
50
|
+
if (text.includes(pattern)) {
|
|
51
|
+
b.click();
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async optIn() {
|
|
62
|
+
return waitForThenClick(".unic #unic-agree");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async test() {
|
|
66
|
+
await wait(1000);
|
|
67
|
+
const res = elementExists(".unic .unic-box,.unic .unic-bar");
|
|
68
|
+
return !res;
|
|
69
|
+
}
|
|
70
|
+
}
|
package/lib/rules.ts
CHANGED
|
@@ -28,7 +28,8 @@ export type AutoConsentRuleStep = { optional?: boolean } & Partial<
|
|
|
28
28
|
Partial<WaitForThenClickRule> &
|
|
29
29
|
Partial<WaitRule> &
|
|
30
30
|
Partial<UrlRule> &
|
|
31
|
-
Partial<HideRule
|
|
31
|
+
Partial<HideRule> &
|
|
32
|
+
Partial<IfRule>;
|
|
32
33
|
|
|
33
34
|
export type ElementExistsRule = {
|
|
34
35
|
exists: string;
|
|
@@ -80,3 +81,9 @@ export type HideRule = {
|
|
|
80
81
|
hide: string[];
|
|
81
82
|
method?: HideMethod;
|
|
82
83
|
};
|
|
84
|
+
|
|
85
|
+
export type IfRule = {
|
|
86
|
+
if: Partial<ElementExistsRule> & Partial<ElementVisibleRule>;
|
|
87
|
+
then: AutoConsentRuleStep[];
|
|
88
|
+
else?: AutoConsentRuleStep[];
|
|
89
|
+
};
|
package/lib/web.ts
CHANGED
|
@@ -107,16 +107,36 @@ export default class AutoConsent {
|
|
|
107
107
|
|
|
108
108
|
async _start() {
|
|
109
109
|
enableLogs && console.log(`Detecting CMPs on ${window.location.href}`)
|
|
110
|
-
const
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
110
|
+
const cmps = await this.findCmp(this.config.detectRetries);
|
|
111
|
+
if (cmps.length > 0) {
|
|
112
|
+
const popupLookups: Promise<boolean>[] = [];
|
|
113
|
+
for (const cmp of cmps) {
|
|
114
|
+
enableLogs && console.log("detected CMP:", cmp.name, window.location.href);
|
|
115
|
+
this.sendContentMessage({
|
|
116
|
+
type: 'cmpDetected',
|
|
117
|
+
url: location.href,
|
|
118
|
+
cmp: cmp.name,
|
|
119
|
+
}); // notify the browser
|
|
120
|
+
popupLookups.push(this.waitForPopup(cmp).then((isOpen) => {
|
|
121
|
+
if (isOpen) {
|
|
122
|
+
if (!this.foundCmp) {
|
|
123
|
+
this.foundCmp = cmp;
|
|
124
|
+
}
|
|
125
|
+
this.sendContentMessage({
|
|
126
|
+
type: 'popupFound',
|
|
127
|
+
cmp: cmp.name,
|
|
128
|
+
url: location.href,
|
|
129
|
+
}); // notify the browser
|
|
130
|
+
return true;
|
|
131
|
+
} else {
|
|
132
|
+
return Promise.reject(`${cmp.name} popup not found`);
|
|
133
|
+
}
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const somethingOpen = await Promise.any(popupLookups).catch(() => false);
|
|
138
|
+
|
|
139
|
+
if (!somethingOpen) {
|
|
120
140
|
enableLogs && console.log('no popup found');
|
|
121
141
|
if (this.config.enablePrehide) {
|
|
122
142
|
undoPrehide();
|
|
@@ -124,13 +144,6 @@ export default class AutoConsent {
|
|
|
124
144
|
return false;
|
|
125
145
|
}
|
|
126
146
|
|
|
127
|
-
this.foundCmp = cmp;
|
|
128
|
-
this.sendContentMessage({
|
|
129
|
-
type: 'popupFound',
|
|
130
|
-
cmp: cmp.name,
|
|
131
|
-
url: location.href,
|
|
132
|
-
}); // notify the browser
|
|
133
|
-
|
|
134
147
|
if (this.config.autoAction === 'optOut') {
|
|
135
148
|
return await this.doOptOut();
|
|
136
149
|
} else if (this.config.autoAction === 'optIn') {
|
|
@@ -148,8 +161,7 @@ export default class AutoConsent {
|
|
|
148
161
|
}
|
|
149
162
|
}
|
|
150
163
|
|
|
151
|
-
async findCmp(retries: number): Promise<AutoCMP> {
|
|
152
|
-
let foundCmp: AutoCMP = null;
|
|
164
|
+
async findCmp(retries: number): Promise<AutoCMP[]> {
|
|
153
165
|
const allFoundCmps: AutoCMP[] = [];
|
|
154
166
|
|
|
155
167
|
for (const cmp of this.rules) {
|
|
@@ -161,9 +173,6 @@ export default class AutoConsent {
|
|
|
161
173
|
if (result) {
|
|
162
174
|
enableLogs && console.log(`Found CMP: ${cmp.name}`);
|
|
163
175
|
allFoundCmps.push(cmp);
|
|
164
|
-
if (!foundCmp) {
|
|
165
|
-
foundCmp = cmp;
|
|
166
|
-
}
|
|
167
176
|
}
|
|
168
177
|
} catch (e) {
|
|
169
178
|
enableLogs && console.warn(`error detecting ${cmp.name}`, e);
|
|
@@ -182,7 +191,7 @@ export default class AutoConsent {
|
|
|
182
191
|
});
|
|
183
192
|
}
|
|
184
193
|
|
|
185
|
-
if (
|
|
194
|
+
if (allFoundCmps.length === 0 && retries > 0) {
|
|
186
195
|
return new Promise((resolve) => {
|
|
187
196
|
setTimeout(async () => {
|
|
188
197
|
const result = this.findCmp(retries - 1);
|
|
@@ -191,7 +200,7 @@ export default class AutoConsent {
|
|
|
191
200
|
});
|
|
192
201
|
}
|
|
193
202
|
|
|
194
|
-
return
|
|
203
|
+
return allFoundCmps;
|
|
195
204
|
}
|
|
196
205
|
|
|
197
206
|
async doOptOut(): Promise<boolean> {
|
|
@@ -236,6 +245,7 @@ export default class AutoConsent {
|
|
|
236
245
|
} else {
|
|
237
246
|
enableLogs && console.log(`CMP ${this.foundCmp.name}: opt in on ${window.location.href}`);
|
|
238
247
|
optInResult = await this.foundCmp.optIn();
|
|
248
|
+
enableLogs && console.log(`${this.foundCmp.name}: opt in result ${optInResult}`);
|
|
239
249
|
}
|
|
240
250
|
|
|
241
251
|
if (this.config.enablePrehide) {
|
|
@@ -286,7 +296,7 @@ export default class AutoConsent {
|
|
|
286
296
|
if (!isOpen && retries > 0) {
|
|
287
297
|
return new Promise((resolve) => setTimeout(() => resolve(this.waitForPopup(cmp, retries - 1, interval)), interval));
|
|
288
298
|
}
|
|
289
|
-
enableLogs && console.log(`popup is ${isOpen ? 'open' : 'not open'}`);
|
|
299
|
+
enableLogs && console.log(cmp.name, `popup is ${isOpen ? 'open' : 'not open'}`);
|
|
290
300
|
return isOpen;
|
|
291
301
|
}
|
|
292
302
|
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -106,6 +106,17 @@ Returns true if elements returned from `document.querySelectorAll(selector)` are
|
|
|
106
106
|
```
|
|
107
107
|
Waits until `selector` exists in the page. After `timeout` ms the step fails.
|
|
108
108
|
|
|
109
|
+
### Wait for visibility
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"waitForVisible": "selector",
|
|
114
|
+
"timeout": 1000,
|
|
115
|
+
"check": "any" | "all" | "none"
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
Waits until element is visible in the page. After `timeout` ms the step fails.
|
|
119
|
+
|
|
109
120
|
### Click an element
|
|
110
121
|
```json
|
|
111
122
|
{
|
|
@@ -152,6 +163,24 @@ Hide the elements matched by the selectors. `method` defines how elements are hi
|
|
|
152
163
|
Evaluates `code` in the context of the page. The rule is considered successful if it *evaluates to a truthy value*.
|
|
153
164
|
Eval rules are not 100% reliable because they can be blocked by a CSP policy on the page. Therefore, they should only be used as a last resort when none of the other rules are sufficient.
|
|
154
165
|
|
|
166
|
+
### Conditionals
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"if": { "exists": "selector" },
|
|
171
|
+
"then": [
|
|
172
|
+
{ "click": ".button1" },
|
|
173
|
+
{ "click": ".button3" }
|
|
174
|
+
],
|
|
175
|
+
"else": [
|
|
176
|
+
{ "click": ".button2" }
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Allows to do conditional branching in JSON rules. The `if` section can contain either a "visible" or "exists" rule. Depending on the result of that rule, `then` or `else` sequences will be executed. `else` section is optional.
|
|
182
|
+
The "if" rule is considered successful as long as all rules inside the chosen branch are successful. The other branch, as well as the result of the condition itself, do not affect the result of the whole rule.
|
|
183
|
+
|
|
155
184
|
### Optional actions
|
|
156
185
|
|
|
157
186
|
Any rule can include the `"optional": true` to ignore failure.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Adroll",
|
|
3
|
+
"prehideSelectors": ["#adroll_consent_container"],
|
|
4
|
+
"detectCmp": [{ "exists": "#adroll_consent_container" }],
|
|
5
|
+
"detectPopup": [{ "visible": "#adroll_consent_container" }],
|
|
6
|
+
"optIn": [ { "waitForThenClick": "#adroll_consent_accept" } ],
|
|
7
|
+
"optOut": [ { "waitForThenClick": "#adroll_consent_reject" } ],
|
|
8
|
+
"test": [
|
|
9
|
+
{ "eval": "!document.cookie.includes('__adroll_fpc')" }
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -9,7 +9,12 @@
|
|
|
9
9
|
"click": "button[data-id=awsccc-cb-btn-customize]"
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
|
-
"
|
|
12
|
+
"waitFor": "input[aria-checked]"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"click": "input[aria-checked=true]",
|
|
16
|
+
"all": true,
|
|
17
|
+
"optional": true
|
|
13
18
|
},
|
|
14
19
|
{
|
|
15
20
|
"click": "button[data-id=awsccc-cs-btn-save]"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "axeptio",
|
|
3
|
+
"prehideSelectors": [".axeptio_widget"],
|
|
4
|
+
"detectCmp":
|
|
5
|
+
[
|
|
6
|
+
{
|
|
7
|
+
"exists": ".axeptio_widget"
|
|
8
|
+
}
|
|
9
|
+
],
|
|
10
|
+
"detectPopup":
|
|
11
|
+
[
|
|
12
|
+
{
|
|
13
|
+
"visible": ".axeptio_widget"
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"optIn":
|
|
17
|
+
[
|
|
18
|
+
{
|
|
19
|
+
"waitFor": ".axeptio-widget--open"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"click": "button#axeptio_btn_acceptAll"
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"optOut":
|
|
26
|
+
[
|
|
27
|
+
|
|
28
|
+
{
|
|
29
|
+
"waitFor": ".axeptio-widget--open"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"click": "button#axeptio_btn_dismiss"
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"test":
|
|
36
|
+
[
|
|
37
|
+
{
|
|
38
|
+
"eval": "document.cookie.includes('axeptio_authorized_vendors=%2C%2C')"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "click.io",
|
|
3
|
+
"prehideSelectors": ["#cl-consent"],
|
|
4
|
+
"detectCmp": [{ "exists": "#cl-consent" }],
|
|
5
|
+
"detectPopup": [{ "visible": "#cl-consent" }],
|
|
6
|
+
"optIn": [ { "waitForThenClick": "#cl-consent [data-role=\"b_agree\"]" } ],
|
|
7
|
+
"optOut": [
|
|
8
|
+
{ "waitFor": "#cl-consent [data-role=\"b_options\"]" },
|
|
9
|
+
{ "wait": 500 },
|
|
10
|
+
{ "click": "#cl-consent [data-role=\"b_options\"]" },
|
|
11
|
+
{ "waitFor": ".cl-consent-popup.cl-consent-visible [data-role=\"alloff\"]" },
|
|
12
|
+
{ "click": ".cl-consent-popup.cl-consent-visible [data-role=\"alloff\"]", "all": true },
|
|
13
|
+
{ "click": "[data-role=\"b_save\"]" }
|
|
14
|
+
],
|
|
15
|
+
"test": [
|
|
16
|
+
{ "eval": "document.cookie.includes('__lxG__consent__v2_daisybit=')", "comment": "TODO: this only checks if we interacted at all" }
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Complianz banner",
|
|
3
|
+
"prehideSelectors": ["#cmplz-cookiebanner-container"],
|
|
4
|
+
"detectCmp": [{ "exists": "#cmplz-cookiebanner-container .cmplz-cookiebanner" }],
|
|
5
|
+
"detectPopup": [{ "visible": "#cmplz-cookiebanner-container .cmplz-cookiebanner", "check": "any" }],
|
|
6
|
+
"optIn": [
|
|
7
|
+
{ "waitForThenClick": ".cmplz-cookiebanner .cmplz-accept" }
|
|
8
|
+
],
|
|
9
|
+
"optOut": [
|
|
10
|
+
{ "waitForThenClick": ".cmplz-cookiebanner .cmplz-deny" }
|
|
11
|
+
],
|
|
12
|
+
"test": [ { "eval": "document.cookie.includes('cmplz_banner-status=dismissed')" } ]
|
|
13
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Complianz categories",
|
|
3
|
+
"prehideSelectors": [".cc-type-categories[aria-describedby=\"cookieconsent:desc\"]"],
|
|
4
|
+
"detectCmp": [{ "exists": ".cc-type-categories[aria-describedby=\"cookieconsent:desc\"]" }],
|
|
5
|
+
"detectPopup": [{ "visible": ".cc-type-categories[aria-describedby=\"cookieconsent:desc\"]" }],
|
|
6
|
+
"optIn": [
|
|
7
|
+
{ "click": ".cc-accept-all", "optional": true },
|
|
8
|
+
{ "click": ".cc-allow", "optional": true },
|
|
9
|
+
{ "click": ".cc-dismiss", "optional": true }
|
|
10
|
+
],
|
|
11
|
+
"optOut": [
|
|
12
|
+
{ "click": ".cc-dismiss" }
|
|
13
|
+
],
|
|
14
|
+
"test": [
|
|
15
|
+
{ "eval": "!!document.cookie.match(/cmplz_[^=]+=deny/)" }
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Complianz notice",
|
|
3
|
+
"prehideSelectors": [".cc-type-info[aria-describedby=\"cookieconsent:desc\"]"],
|
|
4
|
+
"detectCmp": [{ "exists": ".cc-type-info[aria-describedby=\"cookieconsent:desc\"]" }],
|
|
5
|
+
"detectPopup": [{ "visible": ".cc-type-info[aria-describedby=\"cookieconsent:desc\"]" }],
|
|
6
|
+
"optIn": [
|
|
7
|
+
{ "click": ".cc-accept-all", "optional": true },
|
|
8
|
+
{ "click": ".cc-allow", "optional": true },
|
|
9
|
+
{ "click": ".cc-dismiss", "optional": true }
|
|
10
|
+
],
|
|
11
|
+
"optOut": [
|
|
12
|
+
{ "hide": ["[aria-describedby=\"cookieconsent:desc\"]"] }
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Complianz optin",
|
|
3
|
+
"prehideSelectors": [".cc-type-opt-in[aria-describedby=\"cookieconsent:desc\"]"],
|
|
4
|
+
"detectCmp": [{ "exists": ".cc-type-opt-in[aria-describedby=\"cookieconsent:desc\"]" }],
|
|
5
|
+
"detectPopup": [{ "visible": ".cc-type-opt-in[aria-describedby=\"cookieconsent:desc\"]" }],
|
|
6
|
+
"optIn": [
|
|
7
|
+
{ "click": ".cc-accept-all", "optional": true },
|
|
8
|
+
{ "click": ".cc-allow", "optional": true },
|
|
9
|
+
{ "click": ".cc-dismiss", "optional": true }
|
|
10
|
+
],
|
|
11
|
+
"optOut": [
|
|
12
|
+
{ "click": ".cc-settings" },
|
|
13
|
+
{ "waitForVisible": "[aria-label=\"cookies preferences popup\"]" },
|
|
14
|
+
{ "click": "[aria-label=\"cookies preferences popup\"] input[type=checkbox]:not([disabled])", "all": true },
|
|
15
|
+
{ "click": "[aria-label=\"cookies preferences popup\"] [aria-label=\"Accept Selected\"]" }
|
|
16
|
+
],
|
|
17
|
+
"test": [
|
|
18
|
+
{ "eval": "!!document.cookie.match(/cookieconsent_preferences_disabled=[^;]+/)" }
|
|
19
|
+
]
|
|
20
|
+
}
|