extended capabilities

This commit is contained in:
botastic 2023-02-26 23:35:53 +01:00
parent ad6ec72e20
commit 2e76be2c50
6 changed files with 639 additions and 361 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
node_modules
config.yaml

31
README.md Normal file
View File

@ -0,0 +1,31 @@
# KVR appointment finder
Have you ever found yourself in the situation where you wanted to book an appointment at the KVR and no slot was available?
Well you could check the website every hour and hope that someone has canceled their appointment or you could automate that shit for you ;)
## How to use
### Configuration
Before searching for appointments you need to configure which type of appointment you are looking for. This is done in the `config.yaml`.
Additionally, you need to configure a Telegram bot that notifies you about the latest search results. First, you need to create a bot. This is done by sending the `BotFather` a message containing the command `/newbot`. It will then prompt you to enter a name and username for the bot. After that you will receive a token which you have to set in the `config.yaml`.
Secondly, you need your personal ChatID. This can be received by the `IDBot` first sending `/start` followed by the `/getid` command. Your ChatID has to be set in the `config.yaml` as well.
### Running the application
You can choose to either run the application in a docker container or directly on your system
#### Docker
```bash
docker build -t kvr .
docker run -it kvr
```
Note that non-Headless mode requires further configuration of the Dockerfile and your system.
#### System
```bash
yarn install
node index.js
```
### Known issues
It has recently been discovered that the dialogue is sometimes guarded by a (fairly simple) captcha. For now the program will simply skip the appointment search and wait for the configured interval.

210
config.yaml Normal file
View File

@ -0,0 +1,210 @@
# TelegramBotToken is the token of the bot you've created
TelegramBotToken: "xxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# TelegramChatID is your personal ChatID
TelegramChatID: "xxxxxxxxx"
# Interval in which the appoints will be checked. Because we do not want to DDoS
# the KVR, a minimum interval of 10 minutes is required.
Interval: 1800000 # 1000 * 60 * 30 ms = 30 min
# Whether to start PlayWrighter in headless mode - mainly for debugging and presentation
Headless: false
# Kind of appointment. See list below for possible values
AppointmentType: "Antrag Personalausweis"
# Name of the citizens office (Bürgerbüro) - only needed when an appointment in a Bürgerbüro is searched for
CitizensOffice: "Pasing"
# Possible appointment types:
# ~ Standesamt
# ~~ Standesamt
# "Kirchenaustritt erklären"
# "Beratungsgespräch Eheanmeldeverfahren"
# "Eheanmeldung ohne Auslandsbezug"
# "Eheanmeldung mit Auslandsbezug"
# "Erklärung Reihenfolge Vornamen"
# "Erklärung 3. Geschlecht"
# ~~ Standesamt Pasing
# "Kirchenaustritt erklären (Standesamt Pasing)"
# "Beratungsgespräch Eheanmeldeverfahren (Standesamt Pasing)"
# "Eheanmeldung ohne Auslandsbezug (Standesamt Pasing)"
# "Eheanmeldung mit Auslandsbezug (Standesamt Pasing)"
# "Erklärung Reihenfolge Vornamen (Standesamt Pasing)"
# "Erklärung 3. Geschlecht (Standesamt Pasing)"
# ~ Führerscheinstelle
# ~~ Internationaler Führerschein
# "Internationalen Führerschein mit vorherigem Tausch in Kartenführerschein beantragen"
# "Internationaler Führerschein bei Besitz eines Kartenführerscheins"
# ~~ Umschreibung eines ausländischen Führerscheins
# "Umschreibung eines ausländischen Führerscheins (kein EU/EWR-Führerschein) beantragen"
# ~~ Führerschein zur Fahrgastbeförderung
# "Ersatz Personenbeförderungsschein wegen Verlust / Diebstahl"
# ~~ Umschreibung Dienstführerschein
# "Dienstführerschein umschreiben"
# ~~ Abholung Führerschein
# "Abholen eines internationalen Führerscheins bei Besitz eines Kartenführerscheins"
# "Abholung eines Führerscheines"
# "Abholung eines Personenbeförderungsscheines"
# ~ Bürgerbüro
# ~~ Meldeangelegenheiten
# "An- oder Ummeldung - Einzelperson"
# "An- oder Ummeldung - Einzelperson mit eigenen Fahrzeugen"
# "An- oder Ummeldung - Familie"
# "An- oder Ummeldung - Familie mit eigenen Fahrzeugen"
# "Meldebescheinigung"
# "Haushaltsbescheinigung"
# "Familienstandsänderung/ Namensänderung"
# ~~ Ausweisdokumente
# "Antrag Personalausweis"
# "Antrag Reisepass/Expressreisepass"
# "Antrag vorläufiger Reisepass"
# "Antrag oder Verlängerung/Aktualisierung Kinderreisepass"
# "Ausweisdokumente - Familie (Minderjährige und deren gesetzlicheVertreter)"
# "eID-Karte beantragen (EU/EWR)"
# "Nachträgliche Anschriftenänderung Personalausweis/Reisepass/eAT"
# "Nachträgliches Einschalten eID / Nachträgliche Änderung PIN"
# "Widerruf der Verlust- oder Diebstahlanzeige von Personalausweis oder Reisepass"
# "Verlust- oder Diebstahlanzeige von Personalausweis"
# "Verlust- oder Diebstahlanzeige von Reisepass"
# ~~ Abholung Ausweisdokumente (Personalausweise, Reisepässe, eID-Karten)
# "Personalausweis, Reisepass oder eID-Karte abholen"
# ~~ Bundeszentralregisterauskunft (Auskunft Gewerbezentralregister)
# "Führungszeugnis beantragen"
# "Gewerbezentralregisterauskunft beantragen natürliche Person"
# "Gewerbezentralregisterauskunft beantragen juristische Person"
# ~~ Beglaubigungen
# "Bis zu 5 Beglaubigungen Unterschrift"
# "Bis zu 5 Beglaubigungen Dokument"
# "Bis zu 20 Beglaubigungen"
# ~~ Zulassungsangelegenheiten
# "Fahrzeug wieder anmelden [Zulassungsangelegenheiten]"
# "Fahrzeug außer Betrieb setzen"
# "Adressänderung in Fahrzeugpapiere eintragen lassen [Zulassungsangelegenheiten]"
# "Namensänderung in Fahrzeugpapiere eintragen lassen"
# ~ Versicherungsamt
# ~~ Rentenauskunft
# "Auskunft Rente"
# "Auskunft Hinterbliebenenrente"
# "Rentenberechnung"
# "Widerspruch"
# "Wartezeitauskunft"
# "Beiträge"
# "Sonstiges RV"
# ~~ Auskunft KW, UV, RV
# "Auskunft KVdR"
# "Familienversicherung"
# "KV für Selbständige"
# "KV für Studenten"
# "Personen ohne KV"
# "Krankengeld"
# "Beitragsrecht"
# "Sonstiges KV"
# "Auskunft PV"
# "Soziale Absicherung von Pflegepersonen"
# "Schwerbehindertenausweis"
# ~~ Rentenanträge
# "Kontenklärung"
# "Altersrente"
# "Rente wegen teilweiser oder voller Erwerbsminderung"
# "Hinterbliebenenrente"
# "Antrag auf Beitragserstattung"
# "Antrag aufmedizinische Rehabilitation"
# "Lebensbescheinigung"
# ~ Amt für Ausbildungsförderung
# ~~ Dienleistungen des AfA
# "Allgemeine Beratung"
# "Antrag abgeben"
# "Unterlagen nachreichen"
# ~ KFZ-Zulassungsstelle
# ~~ Zulassung
# "Fabrikneues Fahrzeug anmelden (mit deutschen Fahrzeugpapieren oder CoC) [Zulassung]"
# "Fahrzeug umschreiben innerhalb Münchens"
# "Fahrzeug umschreiben von außerhalb nach München [Zulassung]"
# "Fahrzeug wieder anmelden [Zulassung]"
# "Vorabzuteilung eines Kennzeichens (z.B. für Fahrten zur Prüforganisation)"
# ~~ Leasing/Finanzierung (Fahrzeugbrief (ZBII) liegt Ihnen nicht vor)
# "Fabrikneues Fahrzeug anmelden (mit deutschen Fahrzeugpapieren oder CoC) [Leasing/Finanzierung]"
# "Fahrzeug umschreiben innerhalb Münchens [Leasing/Finanzierung]"
# "Fahrzeug umschreiben von außerhalb nach München [Leasing/Finanzierung]"
# "Fahrzeug wieder anmelden [Leasing/Finanzierung]"
# "Adressänderung in Fahrzeugpapiere eintragen lassen [Leasing/Finanzierung]"
# "Namensänderung in Fahrzeugpapiere eintragen lassen [Leasing/Finanzierung]"
# "Technische Änderung in Fahrzeugpapiere eintragen lassen [Leasing/Finanzierung]"
# "Saisonkennzeichen beantragen [Leasing/Finanzierung]"
# "Wechselkennzeichen [Leasing/Finanzierung]"
# "Verlust oder Diebstahl der Zulassungsbescheinigung Teil I [Leasing/Finanzierung]"
# "Verlust oder Diebstahl der Kennzeichenschilder [Leasing/Finanzierung]"
# ~~ Import
# "Aus dem Ausland eingeführtes fabrikneues Fahrzeug anmelden"
# "Aus dem Ausland eingeführtes gebrauchtes Fahrzeug anmelden"
# "Kurzzeitkennzeichen für Fahrzeuge mit ausländischen"
# "Vorabzuteilung eines Kennzeichens (z.B. für Fahrten zur Prüforganisation"
# "Zulassung eines selbstgebauten Neufahrzeuges"
# ~~ Änderung der Fahrzeugpapiere
# "Adressänderung in Fahrzeugpapiere eintragen lassen [Änderung der Fahrzeugpapiere]"
# "Namensänderung in Fahrzeugpapiere eintragen lassen [Änderung der Fahrzeugpapiere]"
# "Technische Änderung in Fahrzeugpapiere eintragen lassen [Änderung der Fahrzeugpapiere]"
# ~~ Fahrzeugregister
# "Auskunft aus dem Fahrzeugregister beantragen"
# "Halter- und Datenbestätigungen für ein Kraftfahrzeug beantragen"
# ~~ Besondere Kennzeichen
# "Saisonkennzeichen beantragen [Besondere Kennzeichen]"
# "Kurzzeitkennzeichen beantragen"
# "Wechselkennzeichen [Besondere Kennzeichen]"
# "Historisches Kennzeichen für Oldtimer beantragen"
# "Rotes Dauerkennzeichen für Oldtimer beantragen -"
# "Rote Dauerkennzeichen für Handel und Handwerk -"
# "Ausfuhrkennzeichen"
# ~~ Verlust oder Diebstahl
# "Verlust oder Diebstahl der Zulassungsbescheinigung Teil I [Verlust oder Diebstahl]"
# "Verlust oder Diebstahl der Zulassungsbescheinigung Teil II [Verlust oder Diebstahl]"
# "Verlust oder Diebstahl der Kennzeichenschilder [Verlust oder Diebstahl]"
# ~~ Fahrzeug abmelden
# "Abmeldung"
# "Abmeldung mit Verlust oder Diebstahl der Zulassungsbescheinigung Teil I"
# "Abmeldung mit Verlust oder Diebstahl der Kennzeichen"
# ~~ Versicherungen
# "Bearbeitung von Steuer- und Versicherungsangelegenheiten"
# ~~ Auswärtige Autohäuser
# "Kfz Angelegenheiten für auswärtige Autohäuser"
# ~ Mietspiegel - Überprüfung Mieterhöhung
# ~~ Dienstleistungen des Amtes für Wohnen und Migration
# "Prüfung Mieterhöhung"
# ~ Elternberatungsstelle
# ~~ Alle Dienstleistungen
# "Kurzberatung - Nachfrage zum Bearbeitungsstand"
# "Umfassende Beratung - Wie bekomme ich einen Kita-Platz für mein Kind ?"

467
index.js
View File

@ -1,126 +1,411 @@
const { chromium } = require("playwright");
const fetch = require("node-fetch");
const { chromium } = require('playwright');
const fetch = require('node-fetch');
const yaml = require('js-yaml');
const fs = require('fs');
const TELEGRAM_BOT_TOKEN =
process.env.TELEGRAM_BOT_TOKEN ?? "XXXXXXXXXX:XXXXXXXXXXXXXXXXXX-XXXXXXXXXXX";
const TELEGRAM_CHAT_ID = process.env.TELEGRAM_CHAT_ID ?? "XXXXXXXXX";
const KVR_ID = process.env.KVR_ID ?? 1000102;
const headless = (process.env.HEADLESS ?? true) === true;
const kvrUrl =
"https://terminvereinbarung.muenchen.de/sta/termin/index.php?cts=" + KVR_ID;
const minInterval = 600000 // 1000 * 60 * 10 ms = 10 min
// either overwrite case type here or use KVR_CASE_TYPE_VARIABLE
const personCountSelector = `select[name="CASETYPES[${
process.env.KVT_CASE_TYPE ?? "Kirchenaustritt erklären"
}]"]`;
const interval = 1000 * 60 * 30;
const sendMsg = async (msg, gif, fetchOptions = {}) => {
const sendMsg = async (conf, msg, gif, fetchOptions = {}) => {
fetchOptions.timeout = fetchOptions.timeout || 3000;
let url = `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/`;
let url = `https://api.telegram.org/bot${conf.TelegramBotToken}/`;
if (gif) {
url += `sendvideo?chat_id=${TELEGRAM_CHAT_ID}&caption=${encodeURIComponent(
msg
)}&video=${encodeURIComponent(gif)}`;
url += `sendvideo?chat_id=${conf.TelegramChatID}&caption=${encodeURIComponent(msg)}&video=${encodeURIComponent(gif)}`
} else {
url += `sendmessage?chat_id=${TELEGRAM_CHAT_ID}&text=${encodeURIComponent(
msg
)}`;
url += `sendmessage?chat_id=${conf.TelegramChatID}&text=${encodeURIComponent(msg)}`
}
try {
let response = await (await fetch(url, fetchOptions)).json();
console.log("got telegram response", response)
return response;
} catch (e) {
console.error(new Date().toLocaleString(), e.message);
return false;
}
};
}
const nothingFound = async () => {
await sendMsg(
"Nothing new yet \n" + Date().toLocaleString(),
"https://tenor.com/2pw1.gif"
);
console.log("[log] no new entry found for date " + Date().toLocaleString());
};
const nothingFound = async (conf) => {
await sendMsg(conf, 'Nothing new yet \n' + Date().toLocaleString(), "https://tenor.com/2pw1.gif")
console.log("[log] no new entry found for date " + Date().toLocaleString())
}
const createFindFreeDates = (page) => async () => {
await page.goto(kvrUrl);
console.log("[log] fetching current state");
await page.waitForSelector(personCountSelector);
await page.selectOption(`${personCountSelector}`, "1");
// console.debug("found person selector")
await page.waitForSelector(".WEB_APPOINT_FORWARDBUTTON");
await page.click(".WEB_APPOINT_FORWARDBUTTON");
const createFindFreeDates = (conf, page) => async () => {
// wait for updated page to load
await page.waitForSelector(".nat_calendar td.nat_calendar");
const monthEntries = await page.$$("td.nat_calendar");
await page.goto(conf.Url)
console.log("[log] fetching current state")
console.log("[log] data loaded");
// data has type
/*
{
'Wartezone Kirchenaustritte': {
caption: 'Standesamt Ruppertstrasse',
appoints: {
'2022-12-02': [],
...
'2023-01-07': [],
'2023-01-08': [],
'2023-01-09': [],
'2023-01-10': [],
'2023-01-11': [],
'2023-01-12': [],
'2023-01-13': [],
'2023-01-14': [],
'2023-01-15': [],
'2023-01-16': [],
'2023-01-17': [ '14:15', '14:30', '14:35', '14:40' ],
// since they added captchas let's not bother them too much, simply wait for the next time window
try {
const captcha = page.getByText('Sicherheitsabfrage', { exact: true });
await captcha.waitFor({ timeout: 2000 });
if (await captcha.count() > 0) {
// await page.pause();// debugging
console.log("[error] found a security question. waiting for next execution");
return
}
} catch (e) { }
},
id: '39e1ede3e0400c55c6385221c42cfe23'
console.log('[log] no captcha found, continuing')
// try to find the count selector. on some pages it is invisible by default on others it is visibel from the get go -.-
try {
await page.waitForSelector(conf.PersonCountSelector, { timeout: 300 });
} catch (e) {
console.log("[debug] unable to find selector: ", e);
console.log("[debug] toggling anchors", conf.PersonCountSelector);
// try to toggle all the toggles
const anchors = page.locator('a:visible');
const hrefs = await anchors.evaluateAll((as) => as.map((a) => a.href).filter((href) => href.match(/javascript:toggle/)));
if (hrefs.length === 0) {
console.log("[error] unable to find anchors");
return
}
console.log("[debug] hrefs", hrefs);
for await (const href of hrefs) {
await page.locator(`a[href="${decodeURI(href)}"]`).click();
// on the Bürgerbüro page there are some anchors that lead to a modal being displayed. We have to close it
try {
await page.click('.close:visible', { timeout: 300 });
console.log("[debug] modal found and closed");
} catch (e) {
console.log("[debug] no modal found");
// no modal -> nothing to do
}
}
*/
const data = JSON.parse((await page.evaluate(() => jsonAppoints)) ?? "{}");
if (Object.entries(data).length === 0) {
await nothingFound();
return;
}
//console.log(data)
await page.waitForSelector(conf.PersonCountSelector)
await page.selectOption(`${conf.PersonCountSelector}`, "1")
console.log("[debug] found person selector", conf.PersonCountSelector)
await page.waitForSelector(".WEB_APPOINT_FORWARDBUTTON")
await page.click(".WEB_APPOINT_FORWARDBUTTON")
// for citizens' offices (Bürgerbüros) we also need to select a place
let co = conf.CitizensOffice ?? "";
if (co !== "") {
// select a matching citizens office
try {
await page.locator(`input[value="` + co + `"]`).click();
console.log("[debug] citizens office found and selected")
} catch (e) {
console.log("[error] citizens office cannot be found: ", co)
}
}
// wait for updated page to load
await page.waitForSelector(".nat_calendar td.nat_calendar")
await page.$$("td.nat_calendar")
console.log("[log] data loaded")
// data has type
/*
{
'Wartezone Kirchenaustritte': {
caption: 'Standesamt Ruppertstrasse',
appoints: {
'2022-12-02': [],
...
'2023-01-07': [],
'2023-01-08': [],
'2023-01-09': [],
'2023-01-10': [],
'2023-01-11': [],
'2023-01-12': [],
'2023-01-13': [],
'2023-01-14': [],
'2023-01-15': [],
'2023-01-16': [],
'2023-01-17': [ '14:15', '14:30', '14:35', '14:40' ],
},
id: '39e1ede3e0400c55c6385221c42cfe23'
}
}
*/
const data = JSON.parse(await page.evaluate(() => jsonAppoints) ??
"{}")
if (Object.entries(data).length === 0) {
await nothingFound()
return
}
console.log(data)
// select appointment data
const appointments = Object.entries(data)[0][1].appoints;
const appointments = Object.entries(data)[0][1].appoints
// all entries as a list of [[available, data]]
let nonEmptyDays = Object.entries(appointments).filter(
([key, value]) => value.length !== 0
);
let nonEmptyDays = Object.entries(appointments).filter(([key, value]) => value.length !== 0)
if (nonEmptyDays.length > 0) {
const appointDisplayList = nonEmptyDays.reduce((acc, cur) => {
return `${acc}\n${cur[0]} at ${cur[1].join(",")}`;
}, "");
return `${acc}\n${cur[0]} at ${cur[1].join(",")}`
}, "")
console.log("[log] found entries " + appointDisplayList);
await sendMsg("Found available dates: " + appointDisplayList);
console.log("[log] found entries " + appointDisplayList)
await sendMsg(conf, 'Found available dates: ' + appointDisplayList, "https://tenor.com/bKqEb.gif");
} else {
await nothingFound();
await nothingFound(conf)
}
};
}
const loadConfig = (path) => {
let conf = {}
try {
conf = yaml.load(fs.readFileSync(path, 'utf8'));
} catch (e) {
throw e
}
if (conf.Interval < minInterval) {
throw "please choose a bigger interval (>" + minInterval / (1000 * 60) + "min)";
}
let appointmentTypeMap = new Map([
// Standesamt
// ~ Standesamt
["Kirchenaustritt erklären", { Selector: "Kirchenaustritt erklären", Url: "https://terminvereinbarung.muenchen.de/sta/termin/index.php" }],
["Beratungsgespräch Eheanmeldeverfahren", { Selector: "Beratungsgespräch Eheanmeldeverfahren", Url: "https://terminvereinbarung.muenchen.de/sta/termin/index.php" }],
["Eheanmeldung ohne Auslandsbezug", { Selector: "Eheanmeldung ohne Auslandsbezug", Url: "https://terminvereinbarung.muenchen.de/sta/termin/index.php" }],
["Eheanmeldung mit Auslandsbezug", { Selector: "Eheanmeldung mit Auslandsbezug", Url: "https://terminvereinbarung.muenchen.de/sta/termin/index.php" }],
["Erklärung Reihenfolge Vornamen", { Selector: "Erklärung Reihenfolge Vornamen", Url: "https://terminvereinbarung.muenchen.de/sta/termin/index.php" }],
["Erklärung 3. Geschlecht", { Selector: "Erklärung 3. Geschlecht", Url: "https://terminvereinbarung.muenchen.de/sta/termin/index.php" }],
// ~ Standesamt Pasing
["Kirchenaustritt erklären (Standesamt Pasing)", { Selector: "Kirchenaustritt erklären (Standesamt Pasing)", Url: "https://terminvereinbarung.muenchen.de/sta/termin/index.php" }],
["Beratungsgespräch Eheanmeldeverfahren (Standesamt Pasing)", { Selector: "Beratungsgespräch Eheanmeldeverfahren (Standesamt Pasing)", Url: "https://terminvereinbarung.muenchen.de/sta/termin/index.php" }],
["Eheanmeldung ohne Auslandsbezug (Standesamt Pasing)", { Selector: "Eheanmeldung ohne Auslandsbezug (Standesamt Pasing)", Url: "https://terminvereinbarung.muenchen.de/sta/termin/index.php" }],
["Eheanmeldung mit Auslandsbezug (Standesamt Pasing)", { Selector: "Eheanmeldung mit Auslandsbezug (Standesamt Pasing)", Url: "https://terminvereinbarung.muenchen.de/sta/termin/index.php" }],
["Erklärung Reihenfolge Vornamen (Standesamt Pasing)", { Selector: "Erklärung Reihenfolge Vornamen (Standesamt Pasing)", Url: "https://terminvereinbarung.muenchen.de/sta/termin/index.php" }],
["Erklärung 3. Geschlecht (Standesamt Pasing)", { Selector: "Erklärung 3. Geschlecht (Standesamt Pasing)", Url: "https://terminvereinbarung.muenchen.de/sta/termin/index.php" }],
// Führerscheinstelle
// ~ Internationaler Führerschein
["Internationalen Führerschein mit vorherigem Tausch in Kartenführerschein beantragen", { Selector: "FS Internationaler FS beantragen", Url: "https://terminvereinbarung.muenchen.de/fs/termin/index.php" }],
["Internationaler Führerschein bei Besitz eines Kartenführerscheins", { Selector: "FS Internationaler FS bei Besitz", Url: "https://terminvereinbarung.muenchen.de/fs/termin/index.php" }],
// ~ Umschreibung eines ausländischen Führerscheins
["Umschreibung eines ausländischen Führerscheins (kein EU/EWR-Führerschein) beantragen", { Selector: "FS Umschreibung Ausländischer FS", Url: "https://terminvereinbarung.muenchen.de/fs/termin/index.php" }],
// ~ Führerschein zur Fahrgastbeförderung
["Ersatz Personenbeförderungsschein wegen Verlust / Diebstahl", { Selector: "FS Ersatz PBS", Url: "https://terminvereinbarung.muenchen.de/fs/termin/index.php" }],
// ~ Umschreibung Dienstführerschein
["Dienstführerschein umschreiben", { Selector: "FS Dienstführerschein umschreiben", Url: "https://terminvereinbarung.muenchen.de/fs/termin/index.php" }],
// ~ Abholung Führerschein
["Abholen eines internationalen Führerscheins bei Besitz eines Kartenführerscheins", { Selector: "FS Internationaler FS bei Besitz", Url: "https://terminvereinbarung.muenchen.de/fs/termin/index.php" }],// this actually the same as when applying for an international license
["Abholung eines Führerscheines", { Selector: "FS Abholung Führerschein", Url: "https://terminvereinbarung.muenchen.de/fs/termin/index.php" }],
["Abholung eines Personenbeförderungsscheines", { Selector: "FS Abholung eines Personenbeförderungsscheines", Url: "https://terminvereinbarung.muenchen.de/fs/termin/index.php" }],
// Bürgerbüro
// ~ Meldeangelegenheiten
["An- oder Ummeldung - Einzelperson", { Selector: "An- oder Ummeldung - Einzelperson", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["An- oder Ummeldung - Einzelperson mit eigenen Fahrzeugen", { Selector: "An- oder Ummeldung - Einzelperson mit eigenen Fahrzeugen", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["An- oder Ummeldung - Familie", { Selector: "An- oder Ummeldung - Familie", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["An- oder Ummeldung - Familie mit eigenen Fahrzeugen", { Selector: "An- oder Ummeldung - Familie mit eigenen Fahrzeugen", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Meldebescheinigung", { Selector: "Meldebescheinigung", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Haushaltsbescheinigung", { Selector: "Haushaltsbescheinigung", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Familienstandsänderung/ Namensänderung", { Selector: "Familienstandsänderung/ Namensänderung", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
// ~ Ausweisdokumente
["Antrag Personalausweis", { Selector: "Antrag Personalausweis", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Antrag Reisepass/Expressreisepass", { Selector: "Antrag Reisepass/Expressreisepass", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Antrag vorläufiger Reisepass", { Selector: "Antrag vorläufiger Reisepass", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Antrag oder Verlängerung/Aktualisierung Kinderreisepass", { Selector: "Antrag oder Verlängerung/Aktualisierung Kinderreisepass", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Ausweisdokumente - Familie (Minderjährige und deren gesetzlicheVertreter)", { Selector: "Ausweisdokumente - Familie (Minderjährige und deren gesetzliche Vertreter)", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["eID-Karte beantragen (EU/EWR)", { Selector: "eID-Karte beantragen (EU/EWR)", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Nachträgliche Anschriftenänderung Personalausweis/Reisepass/eAT", { Selector: "Nachträgliche Anschriftenänderung Personalausweis/Reisepass/eAT", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Nachträgliches Einschalten eID / Nachträgliche Änderung PIN", { Selector: "Nachträgliches Einschalten eID / Nachträgliche Änderung PIN", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Widerruf der Verlust- oder Diebstahlanzeige von Personalausweis oder Reisepass", { Selector: "Widerruf der Verlust- oder Diebstahlanzeige von Personalausweis oder Reisepass", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Verlust- oder Diebstahlanzeige von Personalausweis", { Selector: "Verlust- oder Diebstahlanzeige von Personalausweis", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Verlust- oder Diebstahlanzeige von Reisepass", { Selector: "Verlust- oder Diebstahlanzeige von Reisepass", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
// ~ Abholung Ausweisdokumente (Personalausweise, Reisepässe, eID-Karten)
["Personalausweis, Reisepass oder eID-Karte abholen", { Selector: "Personalausweis, Reisepass oder eID-Karte abholen", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
// ~ Bundeszentralregisterauskunft (Auskunft Gewerbezentralregister)
["Führungszeugnis beantragen", { Selector: "Führungszeugnis beantragen", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Gewerbezentralregisterauskunft beantragen natürliche Person", { Selector: "Gewerbezentralregisterauskunft beantragen natürliche Person", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Gewerbezentralregisterauskunft beantragen juristische Person", { Selector: "Gewerbezentralregisterauskunft beantragen juristische Person", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
// ~ Beglaubigungen
["Bis zu 5 Beglaubigungen Unterschrift", { Selector: "Bis zu 5 Beglaubigungen Unterschrift", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Bis zu 5 Beglaubigungen Dokument", { Selector: "Bis zu 5 Beglaubigungen Dokument", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Bis zu 20 Beglaubigungen", { Selector: "Bis zu 20 Beglaubigungen", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
// ~ Zulassungsangelegenheiten
["Fahrzeug wieder anmelden [Zulassungsangelegenheiten]", { Selector: "Fahrzeug wieder anmelden", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Fahrzeug außer Betrieb setzen", { Selector: "Fahrzeug außer Betrieb setzen", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Adressänderung in Fahrzeugpapiere eintragen lassen [Zulassungsangelegenheiten]", { Selector: "Adressänderung in Fahrzeugpapiere eintragen lassen", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
["Namensänderung in Fahrzeugpapiere eintragen lassen", { Selector: "Namensänderung in Fahrzeugpapiere eintragen lassen", Url: "https://terminvereinbarung.muenchen.de/bba/termin/index.php" }],
// Versicherungsamt
// ~ Rentenauskunft
["Auskunft Rente", { Selector: "Auskunft Rente", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Auskunft Hinterbliebenenrente", { Selector: "Auskunft Hinterbliebenenrente", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Rentenberechnung", { Selector: "Rentenberechnung", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Widerspruch", { Selector: "Widerspruch", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Wartezeitauskunft", { Selector: "Wartezeitauskunft", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Beiträge", { Selector: "Beiträge", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Sonstiges RV", { Selector: "Sonstiges RV", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
// ~ Auskunft KW, UV, RV
["Auskunft KVdR", { Selector: "Auskunft KVdR", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Familienversicherung", { Selector: "Familienversicherung", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["KV für Selbständige", { Selector: "KV für Selbständige", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["KV für Studenten", { Selector: "KV für Studenten", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Personen ohne KV", { Selector: "Personen ohne KV", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Krankengeld", { Selector: "Krankengeld", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Beitragsrecht", { Selector: "Beitragsrecht", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Sonstiges KV", { Selector: "Sonstiges KV", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Auskunft PV", { Selector: "Auskunft PV", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Soziale Absicherung von Pflegepersonen", { Selector: "Soziale Absicherung von Pflegepersonen", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Schwerbehindertenausweis", { Selector: "Schwerbehindertenausweis", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
// ~ Rentenanträge
["Kontenklärung", { Selector: "Kontenklärung", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Altersrente", { Selector: "Altersrente", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Rente wegen teilweiser oder voller Erwerbsminderung", { Selector: "Rente wegen teilweiser oder voller Erwerbsminderung", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Hinterbliebenenrente", { Selector: "Hinterbliebenenrente", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Antrag auf Beitragserstattung", { Selector: "Antrag auf Beitragserstattung", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Antrag aufmedizinische Rehabilitation", { Selector: "Antrag auf medizinische Rehabilitation", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
["Lebensbescheinigung", { Selector: "Lebensbescheinigung", Url: "https://terminvereinbarung.muenchen.de/va/termin/index.php" }],
// Amt für Ausbildungsförderung
// ~ Dienleistungen des AfA
["Allgemeine Beratung", { Selector: "Allgemeine Beratung", Url: "https://terminvereinbarung.muenchen.de/afa/termin/index.php" }],
["Antrag abgeben", { Selector: "Antrag abgeben, besprechen und sichten", Url: "https://terminvereinbarung.muenchen.de/afa/termin/index.php" }],
["Unterlagen nachreichen", { Selector: "Unterlagen nachreichen", Url: "https://terminvereinbarung.muenchen.de/afa/termin/index.php" }],
// KFZ-Zulassungsstelle
// ~ Zulassung
["Fabrikneues Fahrzeug anmelden (mit deutschen Fahrzeugpapieren oder CoC) [Zulassung]", { Selector: "ZUL Fabrikneues Fahrzeug", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Fahrzeug umschreiben innerhalb Münchens", { Selector: "ZUL Umschreibung innerhalb [Zulassung]", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Fahrzeug umschreiben von außerhalb nach München [Zulassung]", { Selector: "ZUL Umschreibung außerhalb", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Fahrzeug wieder anmelden [Zulassung]", { Selector: "ZUL Wiederanmeldung", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Vorabzuteilung eines Kennzeichens (z.B. für Fahrten zur Prüforganisation)", { Selector: "ZUL Vorabzuteilung", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
// ~ Leasing/Finanzierung (Fahrzeugbrief (ZBII) liegt Ihnen nicht vor)
["Fabrikneues Fahrzeug anmelden (mit deutschen Fahrzeugpapieren oder CoC) [Leasing/Finanzierung]", { Selector: "LEAS Fabrikneues Fahrzeug", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Fahrzeug umschreiben innerhalb Münchens [Leasing/Finanzierung]", { Selector: "LEAS Umschreibung innerhalb", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Fahrzeug umschreiben von außerhalb nach München [Leasing/Finanzierung]", { Selector: "LEAS Umschreibung außerhalb", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Fahrzeug wieder anmelden [Leasing/Finanzierung]", { Selector: "LEAS Wiederanmeldung", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Adressänderung in Fahrzeugpapiere eintragen lassen [Leasing/Finanzierung]", { Selector: "LEAS Adressänderung", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Namensänderung in Fahrzeugpapiere eintragen lassen [Leasing/Finanzierung]", { Selector: "LEAS Namensänderung", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Technische Änderung in Fahrzeugpapiere eintragen lassen [Leasing/Finanzierung]", { Selector: "LEAS Technische Änderung", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Saisonkennzeichen beantragen [Leasing/Finanzierung]", { Selector: "LEAS Saisonkennzeichen", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Wechselkennzeichen [Leasing/Finanzierung]", { Selector: "LEAS Wechselkennzeichen", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Verlust oder Diebstahl der Zulassungsbescheinigung Teil I [Leasing/Finanzierung]", { Selector: "LEAS Verlust Zulassungsbescheinigung Teil I", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Verlust oder Diebstahl der Kennzeichenschilder [Leasing/Finanzierung]", { Selector: "LEAS Verlust Kennzeichen", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
// ~ Import
["Aus dem Ausland eingeführtes fabrikneues Fahrzeug anmelden", { Selector: "ZUL IS Einfuhr Neu Ausland", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Aus dem Ausland eingeführtes gebrauchtes Fahrzeug anmelden", { Selector: "ZUL IS Einfuhr Gebraucht Ausland", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Kurzzeitkennzeichen für Fahrzeuge mit ausländischen", { Selector: "ZUL IS Kurzzeitkennzeichen", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Vorabzuteilung eines Kennzeichens (z.B. für Fahrten zur Prüforganisation", { Selector: "ZUL IS Vorbereitung Kennzeichen", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Zulassung eines selbstgebauten Neufahrzeuges", { Selector: "ZUL IS Eigenbauten Gutachten", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
// ~ Änderung der Fahrzeugpapiere
["Adressänderung in Fahrzeugpapiere eintragen lassen [Änderung der Fahrzeugpapiere]", { Selector: "ZUL Adressänderung", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Namensänderung in Fahrzeugpapiere eintragen lassen [Änderung der Fahrzeugpapiere]", { Selector: "ZUL Namensänderung", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Technische Änderung in Fahrzeugpapiere eintragen lassen [Änderung der Fahrzeugpapiere]", { Selector: "ZUL Technische Änderung", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
// ~ Fahrzeugregister
["Auskunft aus dem Fahrzeugregister beantragen", { Selector: "ZUL Auskunft", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Halter- und Datenbestätigungen für ein Kraftfahrzeug beantragen", { Selector: "ZUL Halter- und Datenbestätigung", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
// ~ Besondere Kennzeichen
["Saisonkennzeichen beantragen [Besondere Kennzeichen]", { Selector: "ZUL Saisonkennzeichen", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Kurzzeitkennzeichen beantragen", { Selector: "ZUL Kurzzeitkennzeichen", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Wechselkennzeichen [Besondere Kennzeichen]", { Selector: "ZUL Wechselkennzeichen", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Historisches Kennzeichen für Oldtimer beantragen", { Selector: "ZUL Historisches Kennzeichen", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Rotes Dauerkennzeichen für Oldtimer beantragen -", { Selector: "ZUL Rotes Dauerkennzeichen für Oldtimer beantragen", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Rote Dauerkennzeichen für Handel und Handwerk -", { Selector: "ZO Rote Dauerkennzeichen für Handel und Handwerk", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Ausfuhrkennzeichen", { Selector: "ZO Ausfuhrkennzeichen", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
// ~ Verlust oder Diebstahl
["Verlust oder Diebstahl der Zulassungsbescheinigung Teil I [Verlust oder Diebstahl]", { Selector: "ZUL Verlust Zulassungsbescheinigung Teil I", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Verlust oder Diebstahl der Zulassungsbescheinigung Teil II [Verlust oder Diebstahl]", { Selector: "ZUL Verlust Zulassungsbescheinigung Teil II", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Verlust oder Diebstahl der Kennzeichenschilder [Verlust oder Diebstahl]", { Selector: "ZUL Verlust Kennzeichen", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
// ~ Fahrzeug abmelden
["Abmeldung", { Selector: "ABS Außerbetriebsetzung", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Abmeldung mit Verlust oder Diebstahl der Zulassungsbescheinigung Teil I", { Selector: "ABS Außerbetriebsetzung mit Verlust oder Diebstahl der Zulassungsbescheinigung Teil I", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
["Abmeldung mit Verlust oder Diebstahl der Kennzeichen", { Selector: "ABS Außerbetriebsetzung mit Verlust oder Diebstahl Kennzeichen", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
// ~ Versicherungen
["Bearbeitung von Steuer- und Versicherungsangelegenheiten", { Selector: "VER Bearbeitung von Steuer- und Versicherungsangelegenheiten", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
// ~ Auswärtige Autohäuser
["Kfz Angelegenheiten für auswärtige Autohäuser", { Selector: "AUSW Kombi", Url: "https://terminvereinbarung.muenchen.de/kfz/termin/index.php" }],
// Mietspiegel - Überprüfung Mieterhöhung
// ~ Dienstleistungen des Amtes für Wohnen und Migration
["Prüfung Mieterhöhung", { Selector: "Prüfung Mieterhöhung", Url: "https://terminvereinbarung.muenchen.de/soz/termin/index.php" }],
// Elternberatungsstelle
// ~ Alle Dienstleistungen
["Kurzberatung - Nachfrage zum Bearbeitungsstand", { Selector: "Allgemeine Kurzberatung", Url: "https://terminvereinbarung.muenchen.de/ebs/termin/index.php" }],
["Umfassende Beratung - Wie bekomme ich einen Kita-Platz für mein Kind ?", { Selector: "Umfassende Beratung zur Betreungsplatzsuche", Url: "https://terminvereinbarung.muenchen.de/ebs/termin/index.php" }],
]);
// ensure the configuration is valid
if (!appointmentTypeMap.has(conf.AppointmentType)) {
throw "invalid appointment type: " + conf.appointmentType;
}
conf.PersonCountSelector = `select[name="CASETYPES[` + appointmentTypeMap.get(conf.AppointmentType).Selector + `]"]`;
conf.Url = appointmentTypeMap.get(conf.AppointmentType).Url;
conf.CitizensOffice = conf.CitizensOffice ?? ""
if (conf.CitizensOffice !== "") {
conf.CitizensOffice = "Bürgerbüro " + conf.CitizensOffice;
}
if (appointmentTypeMap.get(conf.AppointmentType).Url === "https://terminvereinbarung.muenchen.de/bba/termin/index.php") {
if (conf.CitizensOffice === "") {
throw "appointment in citizens's office but not location given: " + conf.appointmentType;
}
} else {
// set the value to be empty so the selection will be skipped later on
conf.CitizensOffice = ""
}
console.debug(conf);
return conf
}
(async () => {
console.log("[log] starting playwright with chromium backend");
const browser = await chromium.launch({ headless });
const context = await browser.newContext({});
const page = await context.newPage();
console.log("[log] browser running...");
const findFreeDates = createFindFreeDates(page);
findFreeDates();
console.log("[log] started periodic check every " + interval + " seconds");
setInterval(findFreeDates, interval);
})();
console.log("[log] reading config")
try {
const conf = loadConfig('./config.yaml')
console.log("[log] starting playwright with chromium backend")
let headless = conf.Headless
const browser = await chromium.launch({ headless })
const context = await browser.newContext({})
const page = await context.newPage()
console.log("[log] browser running...")
const findFreeDates = createFindFreeDates(conf, page)
findFreeDates()
console.log("[log] started periodic check every " + conf.Interval / 1000 + " seconds")
setInterval(findFreeDates, conf.Interval)
} catch (e) {
console.log(e)
}
})()

View File

@ -5,10 +5,11 @@
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"playwright": "^1.12.2",
"node-fetch": "2.6.1"
"js-yaml": "^4.1.0",
"node-fetch": "2.6.1",
"playwright": "^1.12.2"
},
"scripts": {
"start": "node index.js"
}
}
}

284
yarn.lock
View File

@ -2,281 +2,31 @@
# yarn lockfile v1
"@types/node@*":
version "15.12.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.4.tgz#e1cf817d70a1e118e81922c4ff6683ce9d422e26"
integrity sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA==
"@types/yauzl@^2.9.1":
version "2.9.1"
resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.1.tgz#d10f69f9f522eef3cf98e30afb684a1e1ec923af"
integrity sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==
dependencies:
"@types/node" "*"
agent-base@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
dependencies:
debug "4"
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
buffer-crc32@~0.2.3:
version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
commander@^6.1.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
debug@4, debug@^4.1.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
dependencies:
ms "2.1.2"
end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
dependencies:
once "^1.4.0"
escape-string-regexp@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
extract-zip@^2.0.1:
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
dependencies:
debug "^4.1.1"
get-stream "^5.1.0"
yauzl "^2.10.0"
optionalDependencies:
"@types/yauzl" "^2.9.1"
fd-slicer@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=
dependencies:
pend "~1.2.0"
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
get-stream@^5.1.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
dependencies:
pump "^3.0.0"
glob@^7.1.3:
version "7.1.7"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
graceful-fs@^4.2.4:
version "4.2.6"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
https-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
dependencies:
agent-base "6"
debug "4"
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
dependencies:
once "^1.3.0"
wrappy "1"
inherits@2:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
jpeg-js@^0.4.2:
version "0.4.3"
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.3.tgz#6158e09f1983ad773813704be80680550eff977b"
integrity sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==
mime@^2.4.6:
version "2.5.2"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe"
integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==
minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
dependencies:
brace-expansion "^1.1.7"
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
argparse "^2.0.1"
node-fetch@2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
once@^1.3.0, once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
dependencies:
wrappy "1"
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
pend@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
playwright-core@1.29.2:
version "1.29.2"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.29.2.tgz#2e8347e7e8522409f22b244e600e703b64022406"
integrity sha512-94QXm4PMgFoHAhlCuoWyaBYKb92yOcGVHdQLoxQ7Wjlc7Flg4aC/jbFW7xMR52OfXMVkWicue4WXE7QEegbIRA==
playwright@^1.12.2:
version "1.12.2"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.12.2.tgz#a484447177b061dd76247734fe65d77e3fb139fa"
integrity sha512-tSZGeILY70T4imhCMCsvzhoaDm9baosIG5fQncSWprpjVc/X4yYdBQCLBMvOi98H50hvu9fhgy2hpsgFKCsUaw==
version "1.29.2"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.29.2.tgz#d6a0a3e8e44f023f7956ed19ffa8af915a042769"
integrity sha512-hKBYJUtdmYzcjdhYDkP9WGtORwwZBBKAW8+Lz7sr0ZMxtJr04ASXVzH5eBWtDkdb0c3LLFsehfPBTRfvlfKJOA==
dependencies:
commander "^6.1.0"
debug "^4.1.1"
extract-zip "^2.0.1"
https-proxy-agent "^5.0.0"
jpeg-js "^0.4.2"
mime "^2.4.6"
pngjs "^5.0.0"
progress "^2.0.3"
proper-lockfile "^4.1.1"
proxy-from-env "^1.1.0"
rimraf "^3.0.2"
stack-utils "^2.0.3"
ws "^7.4.6"
yazl "^2.5.1"
pngjs@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb"
integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==
progress@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
proper-lockfile@^4.1.1:
version "4.1.2"
resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f"
integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==
dependencies:
graceful-fs "^4.2.4"
retry "^0.12.0"
signal-exit "^3.0.2"
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
pump@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"
retry@^0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=
rimraf@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
dependencies:
glob "^7.1.3"
signal-exit@^3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
stack-utils@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277"
integrity sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==
dependencies:
escape-string-regexp "^2.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
ws@^7.4.6:
version "7.5.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.0.tgz#0033bafea031fb9df041b2026fc72a571ca44691"
integrity sha512-6ezXvzOZupqKj4jUqbQ9tXuJNo+BR2gU8fFRk3XCP3e0G6WT414u5ELe6Y0vtp7kmSJ3F7YWObSNr1ESsgi4vw==
yauzl@^2.10.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
dependencies:
buffer-crc32 "~0.2.3"
fd-slicer "~1.1.0"
yazl@^2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35"
integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==
dependencies:
buffer-crc32 "~0.2.3"
playwright-core "1.29.2"