lotsa stuff
This commit is contained in:
parent
8d34088021
commit
a519dbe814
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
web-ext-artifacts
|
@ -1,55 +1,42 @@
|
|||||||
|
"use strict";
|
||||||
// Put all the javascript code here, that you want to execute after page load.
|
// Put all the javascript code here, that you want to execute after page load.
|
||||||
|
|
||||||
let bcFilled = false;
|
let bcFilled = false;
|
||||||
let bdayFilled = false;
|
let bdayFilled = false;
|
||||||
let clickThroughForms = false;
|
let currentStage;
|
||||||
|
|
||||||
function clickContinue() {
|
function executeStage(node) {
|
||||||
if (bdayFilled && bcFilled) {
|
if (node.nodeType === 1) {
|
||||||
document.querySelector('.fahrgastrechte-bahn-card-auswahl button.fahrgastrechte-continue-button')?.dispatchEvent(new Event('click'));
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function processMutations(mutationList, observer) {
|
function processMutations(mutationList, observer) {
|
||||||
for (const mutation of mutationList) {
|
for (const mutation of mutationList) {
|
||||||
if (mutation.type === "childList") {
|
if (mutation.type === "childList") {
|
||||||
mutation.addedNodes.forEach(node => {
|
mutation.addedNodes.forEach(executeStage);
|
||||||
if (node.nodeType === 1) {
|
|
||||||
if (node.classList.contains("antrag-starten")) {
|
|
||||||
node.querySelector('button.test-antrag-starten-button').dispatchEvent(new Event('click', { bubbles: true }));
|
|
||||||
}
|
|
||||||
else if (node.classList.contains("fahrgastrechte-bahn-card-auswahl")) {
|
|
||||||
node.querySelectorAll('input').forEach(e => {
|
|
||||||
if (e.name === "fahrgastrechte-bahn-card-nummer") {
|
|
||||||
fillBcnum().then(clickContinue);
|
|
||||||
} else if (e.name === "fahrgastrechte-bahn-card-auswahl-geburts-datum") {
|
|
||||||
fillBday().then(clickContinue);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (clickThroughForms) {
|
|
||||||
if (node.classList.contains("antrags-typ-auswahl")) {
|
|
||||||
node.querySelector('input#antragstyp-verspaetung').dispatchEvent(new Event('change'));
|
|
||||||
} else if (node.classList.contains("verspaetungs-auswahl")) {
|
|
||||||
node.querySelector('#verspaetungstyp-mehr-als-stunde').dispatchEvent(new Event('change'));
|
|
||||||
} else if (node.classList.contains("verspaetung-bestaetigung")) {
|
|
||||||
node.querySelector('button.fahrgastrechte-continue-button').dispatchEvent(new Event('click', { bubbles: true }));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clickContinue();
|
|
||||||
}
|
}
|
||||||
|
let clickThroughForms;
|
||||||
let observer = new MutationObserver(processMutations);
|
let observer = new MutationObserver(processMutations);
|
||||||
const addObserver = () => {
|
const addObserver = () => {
|
||||||
browser.storage.sync.get('autocontinue').then(v => {
|
browser.storage.sync.get('autocontinue').then(v => {
|
||||||
clickThroughForms = !!v.autocontinue;
|
clickThroughForms = !!v.autocontinue;
|
||||||
}).then(() => {
|
|
||||||
observer.observe(document.body, {
|
observer.observe(document.body, {
|
||||||
childList: true, subtree: true
|
childList: true, subtree: true
|
||||||
})
|
})
|
||||||
@ -58,25 +45,98 @@ const addObserver = () => {
|
|||||||
|
|
||||||
addObserver();
|
addObserver();
|
||||||
|
|
||||||
async function fillBcnum() {
|
const startClaim = {
|
||||||
let bcNumberInput = document.querySelector('input[name=fahrgastrechte-bahn-card-nummer]');
|
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 => {
|
browser.storage.sync.get('bcnum').then(v => {
|
||||||
let bcNum = v.bcnum || null;
|
let bcNum = v.bcnum || null;
|
||||||
if (bcNum !== null && bcNum !== "") {
|
if (bcNum !== null && bcNum !== "") {
|
||||||
bcNumberInput.value = bcNum;
|
bcNumberInput.value = bcNum;
|
||||||
bcNumberInput.dispatchEvent(new Event('input', { bubbles: true }));
|
bcNumberInput.dispatchEvent(new Event('input', { bubbles: true }));
|
||||||
bcFilled = true;
|
return true;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
async function fillBday() {
|
function fillBday(birthdayInput) {
|
||||||
let birthdayInput = document.querySelector('input[name=fahrgastrechte-bahn-card-auswahl-geburts-datum');
|
|
||||||
browser.storage.sync.get('bday').then(v => {
|
browser.storage.sync.get('bday').then(v => {
|
||||||
bDay = v.bday || null;
|
const bDay = v.bday || null;
|
||||||
if (bDay !== null && bDay !== "") {
|
if (bDay !== null && bDay !== "") {
|
||||||
birthdayInput.value = bDay;
|
birthdayInput.value = bDay;
|
||||||
birthdayInput.dispatchEvent(new Event('input', { bubbles: true }));
|
birthdayInput.dispatchEvent(new Event('input', { bubbles: true }));
|
||||||
bdayFilled = true;
|
bdayFilled = 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 }))
|
||||||
|
}
|
||||||
|
let stages = [
|
||||||
|
startClaim, fillData, clickContinue, iWasDelayed, moreThan60Minutes, continueToForm
|
||||||
|
];
|
||||||
|
@ -2,14 +2,16 @@
|
|||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "BC100 Autofill",
|
"name": "BC100 Autofill",
|
||||||
"description": "Autofills your BahnCard 100 number and birthday into the passenger rights claim form.",
|
"description": "Autofills your BahnCard 100 number and birthday into the passenger rights claim form.",
|
||||||
"version": "0.0.1",
|
"version": "0.0.2",
|
||||||
"icons": {
|
"icons": {
|
||||||
"64": "icons/icon.png"
|
"64": "icons/icon.png"
|
||||||
},
|
},
|
||||||
"content_scripts": [
|
"content_scripts": [
|
||||||
{
|
{
|
||||||
"matches": [
|
"matches": [
|
||||||
"https://www.bahn.de/buchung/fahrgastrechte?einstiegtyp=BC100"
|
"https://www.bahn.de/buchung/fahrgastrechte?einstiegtyp=BC100",
|
||||||
|
"https://www.bahn.de/buchung/fahrgastrechte?lang=*&einstiegtyp=BC100",
|
||||||
|
"https://int.bahn.de/*/buchung/fahrgastrechte?einstiegtyp=BC100"
|
||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"content_script.js"
|
"content_script.js"
|
||||||
|
@ -8,21 +8,25 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<form>
|
<form>
|
||||||
<fieldset>
|
<label class="item">
|
||||||
<label for="bcnum">The number of your BahnCard 100</label>
|
<span class="fh">Your BahnCard 100 number</span><br />
|
||||||
<input name="bcnum" id="bcnum" type="text" pattern="70814[0-9]{11}" />
|
<span class="sh">The number on the front of your card starting with <span class="ms">7081</span>.</span><br>
|
||||||
</fieldset>
|
<input name="bcnum" id="bcnum" type="text" pattern="70814[0-9]{11}" required
|
||||||
<fieldset>
|
title="Your BahnCard number is 16 digits long and starts with 7081." />
|
||||||
<label for="birthday">Your date of birth</label>
|
</label>
|
||||||
<input name="birthday" id="birthday" type="date" />
|
<label class="item">
|
||||||
</fieldset>
|
<span class="fh">Your date of birth</span><br>
|
||||||
<fieldset>
|
<input name="birthday" id="birthday" type="date" required />
|
||||||
<label for="autocontinue">Automatically continue to the "I was delayed by more than 60 minutes" screen</label>
|
</label>
|
||||||
<input name="autocontinue" id="autocontinue" type="checkbox" />
|
<label>
|
||||||
</fieldset>
|
<span class="fh">Skip questionnaire</span><br>
|
||||||
<button type="submit">Save</button>
|
<span class="sh">Automatically answer "I was delayed, by more than 60 minutes."</span><br>
|
||||||
|
<input name="autocontinue" id="autocontinue" type="checkbox" required />
|
||||||
|
</label>
|
||||||
|
<div class="item"><button type="submit">Save</button><span id="success"></span></div>
|
||||||
|
<p id="errors"></p>
|
||||||
</form>
|
</form>
|
||||||
<script src="script.js"></script>
|
<script type="module" src="script.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
@ -1,16 +1,63 @@
|
|||||||
async function saveOptions(e) {
|
function luhnValidate(cardNumber) {
|
||||||
console.log("Saving options.");
|
cardNumber = String(cardNumber).replace(/[\s]/g, "");
|
||||||
e.preventDefault();
|
let odd = false;
|
||||||
let bcNum = document.querySelector("#bcnum").value;
|
let total = 0;
|
||||||
let bDay = document.querySelector('#birthday').value;
|
let position, doubledPos;
|
||||||
let autoContinue = document.querySelector('#autocontinue').checked;
|
|
||||||
|
if (!/^[0-9]+$/.test(cardNumber)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = cardNumber.length; i > 0; i--) {
|
||||||
|
position = parseInt(cardNumber[i - 1]);
|
||||||
|
if (!odd) {
|
||||||
|
total += position;
|
||||||
|
} else {
|
||||||
|
doubledPos = position * 2;
|
||||||
|
|
||||||
|
if (doubledPos > 9) {
|
||||||
|
doubledPos -= 9;
|
||||||
|
}
|
||||||
|
total += doubledPos;
|
||||||
|
}
|
||||||
|
odd = !odd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (total !== 0 && (total % 10) === 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function putError(s){
|
||||||
|
document.querySelector('#errors').textContent += s;
|
||||||
|
}
|
||||||
|
function clearError(){
|
||||||
|
document.querySelector('#errors').textContent = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveOptions(ev) {
|
||||||
|
clearError();
|
||||||
|
ev.preventDefault();
|
||||||
|
let bcNum = this.querySelector("#bcnum").value;
|
||||||
|
if (!bcNum.length == 16 || !bcNum.startsWith("70814") || !luhnValidate(bcNum)) {
|
||||||
|
putError("Your BahnCard number is not valid. Please make sure you haven't made any typos.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let bDay = this.querySelector('#birthday').value;
|
||||||
|
if (bDay == ""){
|
||||||
|
putError("Please enter a birthday.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let autoContinue = this.querySelector('#autocontinue').checked;
|
||||||
let options = {
|
let options = {
|
||||||
bcnum: bcNum,
|
bcnum: bcNum,
|
||||||
bday: bDay,
|
bday: bDay,
|
||||||
autocontinue: autoContinue
|
autocontinue: autoContinue
|
||||||
};
|
};
|
||||||
await browser.storage.sync.set(options);
|
browser.storage.sync.set(options).then(() => {
|
||||||
console.log("Saved!");
|
document.querySelector('#success').textContent = "✔";
|
||||||
|
setTimeout(() => {
|
||||||
|
document.querySelector('#success').textContent = '';
|
||||||
|
}, 5000);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function restoreOptions() {
|
async function restoreOptions() {
|
||||||
@ -18,7 +65,7 @@ async function restoreOptions() {
|
|||||||
// let res = await browser.storage.managed.get('colour');
|
// let res = await browser.storage.managed.get('colour');
|
||||||
// document.querySelector("#managed-colour").innerText = res.colour;
|
// document.querySelector("#managed-colour").innerText = res.colour;
|
||||||
|
|
||||||
settings = await browser.storage.sync.get();
|
let settings = await browser.storage.sync.get();
|
||||||
console.log(settings);
|
console.log(settings);
|
||||||
document.querySelector("#bcnum").value = settings.bcnum || "";
|
document.querySelector("#bcnum").value = settings.bcnum || "";
|
||||||
document.querySelector("#birthday").value = settings.bday || "";
|
document.querySelector("#birthday").value = settings.bday || "";
|
||||||
|
@ -1,3 +1,52 @@
|
|||||||
h1 {
|
.fh {
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sh {
|
||||||
|
font-size: 1em;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label.item {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
margin: 8px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ms {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
#errors {
|
||||||
|
color: red;
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:invalid {
|
||||||
|
background-color: rgba(212, 59, 59, 70%);
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus {
|
||||||
|
background-color: revert;
|
||||||
|
}
|
||||||
|
|
||||||
|
#success {
|
||||||
|
color: lightgreen;
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
color-scheme: light dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
color-scheme: dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
5839
package-lock.json
generated
Normal file
5839
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
15
package.json
Normal file
15
package.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/firefox-webext-browser": "^111.0.2",
|
||||||
|
"web-ext": "^7.8.0",
|
||||||
|
"webextension-polyfill": "github:mozilla/webextension-polyfill"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start:firefox": "web-ext run",
|
||||||
|
"debug": "web-ext run --devtools --firefox deved --url https://www.bahn.de/buchung/fahrgastrechte?einstiegtyp=BC100"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"luhn": "^2.4.1",
|
||||||
|
"typescript": "^5.2.2"
|
||||||
|
}
|
||||||
|
}
|
8
web-ext-config.js
Normal file
8
web-ext-config.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
module.exports = {
|
||||||
|
ignoreFiles: [
|
||||||
|
"README.md",
|
||||||
|
"package.json",
|
||||||
|
"web-ext-config.js",
|
||||||
|
".DS_Store"
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user