"use strict"; // Put all the javascript code here, that you want to execute after page load. let currentStage; function executeStage(node) { if (node.nodeType === 1) { if (currentStage === undefined) { currentStage = stages.shift(); } if (currentStage.match(node)) { console.log(currentStage.name, "matched"); console.log(currentStage.name, currentStage.execute(node) ? "executed" : "execution failed"); if (stages.length > 0) { currentStage = stages.shift(); } else { observer.disconnect(); } } else { console.log(currentStage.name, "did not match: ", node); } } } let stages; const personalDataConfigKeys = ["addr__appellation", "addr__firstName", "addr__surName", "addr__email", "addr__street", "addr__postcode", "addr__placename"]; const bankDetailConfigKeys = ["pymt__iban", "pymt__bic"]; function hasConfiguredPersonalData() { browser.storage.sync.get(personalDataConfigKeys).then(res => { return res.length > 0; }) } function hasConfiguredBankDetails() { browser.storage.sync.get(bankDetailConfigKeys).then(res => { return res.length > 0; }); } function processMutations(mutationList, observer) { for (const mutation of mutationList) { if (mutation.type === "childList") { mutation.addedNodes.forEach(executeStage); } } } let clickThroughForms; let observer = new MutationObserver(processMutations); const addObserver = () => { browser.storage.sync.get(['autocontinue', 'enable']).then(v => { clickThroughForms = !!v.autocontinue; if (!!v.enable) { observer.observe(document.body, { childList: true, subtree: true }) } }) }; addObserver(); function fillTextInput(parentNode, selector, value) { const node = parentNode.querySelector(selector); if (node instanceof HTMLInputElement) { node.value = value; node.dispatchEvent(new Event("input", { bubbles: true })); } } const startClaim = { name: "startClaim", match: node => node.classList.contains("antrag-starten"), execute: node => { const startenButton = node.querySelector('button.test-antrag-starten-button'); if (startenButton instanceof HTMLButtonElement) { startenButton.dispatchEvent(new Event('click', { bubbles: true })); return true; } return false; } } function fillBcnum(bcNumberInput) { browser.storage.sync.get('bcnum').then(v => { let bcNum = v.bcnum || null; if (bcNum !== null && bcNum !== "") { bcNumberInput.value = bcNum; bcNumberInput.dispatchEvent(new Event('input', { bubbles: true })); return true; } }) return false; } function fillBday(birthdayInput) { browser.storage.sync.get('bday').then(v => { const bDay = v.bday || null; if (bDay !== null && bDay !== "") { birthdayInput.value = bDay; birthdayInput.dispatchEvent(new Event('input', { bubbles: true })); return true; } }) return false; } const fillData = { name: "fillData", match: node => node.classList.contains("fahrgastrechte-bahn-card-auswahl"), execute: node => { let bcNumField, bdayField; node.querySelectorAll('input').forEach(e => { if (e.name === "fahrgastrechte-bahn-card-nummer") { bcNumField = e; } else if (e.name === "fahrgastrechte-bahn-card-auswahl-geburts-datum") { bdayField = e; } }) fillBcnum(bcNumField); fillBday(bdayField); return true; } } const clickContinue = { name: "clickContinue", match: () => true, execute: e => { const continueButton = document.querySelector('.fahrgastrechte-bahn-card-auswahl button.fahrgastrechte-continue-button'); if (continueButton instanceof Element) { continueButton.dispatchEvent(new Event('click')); return true; } return false; } } const iWasDelayed = { name: "iWasDelayed", match: node => node.classList.contains("antrags-typ-auswahl") && clickThroughForms, execute: node => { const delay = node.querySelector('input#antragstyp-verspaetung'); if (delay instanceof HTMLInputElement) { delay.dispatchEvent(new Event('change')); return true; } return false; } } const moreThan60Minutes = { name: "moreThan60Minutes", match: node => node.classList.contains("verspaetungs-auswahl") && clickThroughForms, execute: node => node.querySelector('#verspaetungstyp-mehr-als-stunde').dispatchEvent(new Event('change')) } const continueToForm = { name: "continueToForm", match: node => node.classList.contains("verspaetung-bestaetigung") && clickThroughForms, execute: node => node.querySelector('button.fahrgastrechte-continue-button').dispatchEvent(new Event('click', { bubbles: true })) } const enterPersonalData = { name: "enterPersonalData", match: node => node.classList.contains("persoenlicheangaben") && hasConfiguredPersonalData(), execute: node => { browser.storage.sync.get(personalDataConfigKeys).then(foundKeys => { console.log("storage returned", foundKeys); //TODO the dropdowns are crazy // if (foundKeys.keys().contains("addr__appellation")){ // let dropDownSelectList = node.querySelector('.test-name-anrede ul.db-web-select-list'); // } for (const [k, v] of Object.entries(foundKeys)) { console.log("processing:", k, ": ", v); switch (k) { case "addr__firstName": console.log("firstName", k, v); fillTextInput(node, ".test-name-vorname input", v); break; case "addr__surName": console.log("lastname", k, v); fillTextInput(node, '.test-name-nachname input', v); break; case "addr__email": console.log("em", k, v); fillTextInput(node, '.persoenlicheangaben__email input', v); break; case "addr__street": console.log("street", k, v); fillTextInput(node, ".test-adresse-strasse input", v); break; case "addr__postcode": fillTextInput(node, ".test-adresse-plz input", v); break; case "addr__placename": fillTextInput(node, ".test-adresse-ort input", v); break; default: console.log(k, ":", v, "did not match"); } } const continueBtn = document.querySelector(".fahrgastrechte-editable__buttons button.fahrgastrechte-continue-button"); if (continueBtn.querySelector("span span.db-web-button__label").textContent == "OK, weiter" && clickThroughForms) { continueBtn.dispatchEvent(new Event("click", { bubbles: true })); } return true; }) }, } const enterPaymentDetails = { name: "enterPaymentDetails", match: node => node.classList.contains("entschaedigung") && hasConfiguredBankDetails(), execute: node => { node.querySelector('#ueberweisung').dispatchEvent(new Event('change')); browser.storage.sync.get(bankDetailConfigKeys).then(results => { console.log(results); for (const [k, v] of Object.entries(results)) { switch (k) { case "pymt__iban": fillTextInput(node, '.test-entschaedigung-iban input', v); break; case "pymt__bic": fillTextInput(node, '.test-entschaedigung-bic input', v); break; } } }) true }, } const defaultStages = [ startClaim, fillData, clickContinue, iWasDelayed, moreThan60Minutes, continueToForm, enterPersonalData, enterPaymentDetails ]; stages = defaultStages;