choose your own adventure
This commit is contained in:
		@@ -1,6 +1,9 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
// Put all the javascript code here, that you want to execute after page load.
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @typedef ("delay"|"nodep"|"abort"|"") DisruptionType
 | 
			
		||||
 */
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @typedef {Object} Stage
 | 
			
		||||
@@ -11,9 +14,14 @@
 | 
			
		||||
 */
 | 
			
		||||
/**
 | 
			
		||||
 * @type Stage
 | 
			
		||||
 * @todo this can now also contain a dict<DisruptionType, Stage>
 | 
			
		||||
 */
 | 
			
		||||
let currentStage;
 | 
			
		||||
const settings = browser.storage.sync;
 | 
			
		||||
/**
 | 
			
		||||
 * @type ("delay"|"nodep"|"abort"|"")
 | 
			
		||||
 */
 | 
			
		||||
let disruption = "";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
@@ -44,22 +52,6 @@ const pressKey = (...keys) => {
 | 
			
		||||
        d(new KeyboardEvent('keyup', { bubbles: true, key: k }));
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
/** @param {Node} node */
 | 
			
		||||
function executeStage(node) {
 | 
			
		||||
    if (node.nodeType === 1) {
 | 
			
		||||
        if (currentStage === undefined) {
 | 
			
		||||
            currentStage = stages.shift();
 | 
			
		||||
        }
 | 
			
		||||
        if (currentStage.match(node)) {
 | 
			
		||||
            console.log(currentStage.name, "matched: ", node);
 | 
			
		||||
            console.log(currentStage.name, currentStage.execute(node) ? "executed" : "execution failed");
 | 
			
		||||
            nextStage();
 | 
			
		||||
        } else {
 | 
			
		||||
            console.log(currentStage.name, "did not match: ", mutation);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let stages;
 | 
			
		||||
const personalDataConfigKeys = [
 | 
			
		||||
    "addr__appellation", "addr__title", "addr__firstName", "addr__surName",
 | 
			
		||||
@@ -88,6 +80,19 @@ function processMutations(mutationList, observer) {
 | 
			
		||||
    if (currentStage === undefined) {
 | 
			
		||||
        currentStage = stages.shift();
 | 
			
		||||
    }
 | 
			
		||||
    if (!("name" in currentStage)){
 | 
			
		||||
        // stages always have a `name`, so this must be the disruption type split
 | 
			
		||||
        if (disruption in currentStage){
 | 
			
		||||
            stages.unshift(...currentStage[disruption]);
 | 
			
		||||
            currentStage = stages.shift();
 | 
			
		||||
        } else if (disruption == "") {
 | 
			
		||||
            // no default action - skip to personal data stuff
 | 
			
		||||
            currentStage = stages.shift();
 | 
			
		||||
            //TODO sniff action and provide field jumps instead
 | 
			
		||||
        } else {
 | 
			
		||||
            console.log("this Stage is invalid, aborting", currentStage);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    for (const mutation of mutationList) {
 | 
			
		||||
        if ('expects' in currentStage) {
 | 
			
		||||
            if (currentStage.expects == 'mutation') {
 | 
			
		||||
@@ -116,7 +121,6 @@ function processMutations(mutationList, observer) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
let clickThroughForms;
 | 
			
		||||
let hasConfiguredBankDetails, hasConfiguredPersonalData;
 | 
			
		||||
let observer = new MutationObserver(processMutations);
 | 
			
		||||
function nextStage() {
 | 
			
		||||
@@ -129,9 +133,9 @@ function nextStage() {
 | 
			
		||||
}
 | 
			
		||||
const addObserver = () => {
 | 
			
		||||
    settings.get(
 | 
			
		||||
        ['autocontinue', 'enable'].concat(personalDataConfigKeys, bankDetailConfigKeys)
 | 
			
		||||
        ['enable', 'defaultAction'].concat(personalDataConfigKeys, bankDetailConfigKeys)
 | 
			
		||||
    ).then(userSettings => {
 | 
			
		||||
        clickThroughForms = !!userSettings.autocontinue;
 | 
			
		||||
        disruption = userSettings.defaultAction || "";
 | 
			
		||||
        hasConfiguredPersonalData = Object.keys(userSettings).filter(k => personalDataConfigKeys.includes(k)).length > 0;
 | 
			
		||||
        hasConfiguredBankDetails = Object.keys(userSettings).filter(k => bankDetailConfigKeys.includes(k)).length > 0;
 | 
			
		||||
        if (!!userSettings.enable) {
 | 
			
		||||
@@ -231,9 +235,21 @@ const clickContinue = {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//TODO construction zone
 | 
			
		||||
const sniffDisruption = {
 | 
			
		||||
    name: "sniffDisruption",
 | 
			
		||||
    match: node => {
 | 
			
		||||
        //delay -> .verspaetungs-auswahl.fahrgastrechte-page__section.test-current-section
 | 
			
		||||
        //nodep -> .fahrplan...., .antrags-typ-auswahl:children("input[name=radioAntragsTyp]"):id(#antragstyp-nicht-angetreten):has-siblings(.db-web-radio-button-container__radio-button-icon--checked)
 | 
			
		||||
        //abort -> .fahrplan...., ...#antragstyp-abgebrochen, An welchem Bahnhof? -> .fahrgastrechte-page__section:has-child(.fahrgastrechte-editable.fahrgastrechte-bahnhof.abbruchbahnhof)
 | 
			
		||||
        //         Weitere Kosten? (.kosten-abfrage.f-p__s.t-c-s:has_child(.db-web-radio-button-container.kosten-abfrage__radio))
 | 
			
		||||
    },
 | 
			
		||||
    execute: () => true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const iWasDelayed = {
 | 
			
		||||
    name: "iWasDelayed",
 | 
			
		||||
    match: node => node.classList.contains("antrags-typ-auswahl") && clickThroughForms,
 | 
			
		||||
    match: node => node.classList.contains("antrags-typ-auswahl"),
 | 
			
		||||
    execute: node => {
 | 
			
		||||
        const delay = $$(node, 'input#antragstyp-verspaetung');
 | 
			
		||||
        if (delay instanceof HTMLInputElement) {
 | 
			
		||||
@@ -246,19 +262,21 @@ const iWasDelayed = {
 | 
			
		||||
 | 
			
		||||
const moreThan60Minutes = {
 | 
			
		||||
    name: "moreThan60Minutes",
 | 
			
		||||
    match: node => node.classList.contains("verspaetungs-auswahl") && clickThroughForms,
 | 
			
		||||
    execute: node => node.querySelector('#verspaetungstyp-mehr-als-stunde').dispatchEvent(new Event('change'))
 | 
			
		||||
    match: node => node.classList.contains("verspaetungs-auswahl"),
 | 
			
		||||
    execute: node => {
 | 
			
		||||
        return node.querySelector('#verspaetungstyp-mehr-als-stunde').dispatchEvent(new Event('change'));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const continueToForm = {
 | 
			
		||||
    name: "continueToForm",
 | 
			
		||||
    match: node => node.classList.contains("verspaetung-bestaetigung") && clickThroughForms,
 | 
			
		||||
    match: node => node.classList.contains("verspaetung-bestaetigung"),
 | 
			
		||||
    execute: node => $$(node, 'button.fahrgastrechte-continue-button').dispatchEvent(_clickEv())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const focusDepartureInput = {
 | 
			
		||||
    name: "focusDepartureInput",
 | 
			
		||||
    match: node => node.classList.contains("fahrplan") && clickThroughForms,
 | 
			
		||||
    match: node => node.classList.contains("fahrplan"),
 | 
			
		||||
    execute: node => {
 | 
			
		||||
        const depInput = $$(node, '.fahrplan__start .fahrplan__haltestelle input');
 | 
			
		||||
        const obs = new IntersectionObserver((entries, intObserver) => {
 | 
			
		||||
@@ -274,7 +292,7 @@ const focusDepartureInput = {
 | 
			
		||||
 | 
			
		||||
const jumpToTimeInput = {
 | 
			
		||||
    name: "jumpToTimeInput",
 | 
			
		||||
    match: node => node.classList.contains("ankunft-zeit") && clickThroughForms,
 | 
			
		||||
    match: node => node.classList.contains("ankunft-zeit"),
 | 
			
		||||
    execute: node => {
 | 
			
		||||
        $$(node, '#fahrgastrechte-ankunft-uhrzeit--db-web-text-input').focus();
 | 
			
		||||
        return true;
 | 
			
		||||
@@ -426,8 +444,8 @@ const enterPaymentDetails = {
 | 
			
		||||
}
 | 
			
		||||
const defaultStages = [
 | 
			
		||||
    startClaim, fillData, clickContinue,
 | 
			
		||||
    iWasDelayed, moreThan60Minutes, continueToForm,
 | 
			
		||||
    focusDepartureInput, jumpToTimeInput,
 | 
			
		||||
    {"delay": [iWasDelayed, moreThan60Minutes, continueToForm,
 | 
			
		||||
        focusDepartureInput, jumpToTimeInput], "nodep": [], "abort": []},
 | 
			
		||||
    activateAppellationDropdown, enterAppellationAndActivateTitleDropdown,
 | 
			
		||||
    enterTitleAndActivateCountryDropdown, enterCountry,
 | 
			
		||||
    enterTextPersonalData, /* continueToPayout, */ enterPaymentDetails
 | 
			
		||||
 
 | 
			
		||||
@@ -16,9 +16,13 @@
 | 
			
		||||
        <input name="enable" id="enable" type="checkbox" />
 | 
			
		||||
      </label>
 | 
			
		||||
      <label class="item">
 | 
			
		||||
        <span class="fh">Skip questionnaire</span>
 | 
			
		||||
        <input name="autocontinue" id="autocontinue" type="checkbox" />
 | 
			
		||||
        <span class="sh">Automatically answer "I was delayed, by more than 60 minutes."</span>
 | 
			
		||||
        <span class="fh">Default action</span>
 | 
			
		||||
        <select class="default_action" id="default_action">
 | 
			
		||||
          <option value="">None</option>
 | 
			
		||||
          <option value="delay">I arrived >60 min late</option>
 | 
			
		||||
          <option value="nodep">I did not start the trip</option>
 | 
			
		||||
          <option value="abort">I returned home</option>
 | 
			
		||||
        </select>
 | 
			
		||||
      </label>
 | 
			
		||||
    </fieldset>
 | 
			
		||||
    <button id="all-get-from-profile">Get my personal data from my profile</button>
 | 
			
		||||
 
 | 
			
		||||
@@ -75,8 +75,8 @@ async function saveOptions(ev) {
 | 
			
		||||
    putError("Please enter a birthday.");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  let autoContinue = this.querySelector('#autocontinue').checked;
 | 
			
		||||
  let enable = this.querySelector('#enable').checked;
 | 
			
		||||
  let defaultAction = this.querySelector('#default_action').value;
 | 
			
		||||
  let title = this.querySelector('#title').value;
 | 
			
		||||
  let title_addl = this.querySelector('#title_addl').value;
 | 
			
		||||
  let firstName = this.querySelector('#firstname').value;
 | 
			
		||||
@@ -95,8 +95,8 @@ async function saveOptions(ev) {
 | 
			
		||||
  let options = {
 | 
			
		||||
    bcnum: bcNum,
 | 
			
		||||
    bday: bDay,
 | 
			
		||||
    autocontinue: autoContinue,
 | 
			
		||||
    enable: enable,
 | 
			
		||||
    defaultAction: defaultAction,
 | 
			
		||||
    addr__appellation: title,
 | 
			
		||||
    addr__title: title_addl,
 | 
			
		||||
    addr__firstName: firstName,
 | 
			
		||||
@@ -131,7 +131,7 @@ async function restoreOptions() {
 | 
			
		||||
  document.querySelector('#enable').checked = settings.enable || true;
 | 
			
		||||
  document.querySelector("#bcnum").value = settings.bcnum || "";
 | 
			
		||||
  document.querySelector("#birthday").value = settings.bday || "";
 | 
			
		||||
  document.querySelector("#autocontinue").checked = settings.autocontinue || false;
 | 
			
		||||
  document.querySelector("#default_action").value = settings.defaultAction || "";
 | 
			
		||||
  document.querySelector('#title').value = settings.addr__appellation || "";
 | 
			
		||||
  document.querySelector('#title_addl').value = settings.addr__title || "";
 | 
			
		||||
  document.querySelector('#firstname').value = settings.addr__firstName || "";
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user