Skip to content

Instantly share code, notes, and snippets.

@copitz
Created August 28, 2019 07:28
Show Gist options
  • Save copitz/b847bb9cc35cd07d82d8d650cabfe023 to your computer and use it in GitHub Desktop.
Save copitz/b847bb9cc35cd07d82d8d650cabfe023 to your computer and use it in GitHub Desktop.
Monitor free dates at Standesamt Leipzig - freie Termine bei Standesamt Leipzig überwachen
const { execFileSync } = require('child_process')
const notifier = require('node-notifier');
const logFile = require('path').resolve(require('os').homedir(), '.standesamt-log')
const fs = require('fs')
const path = require('path')
const casper = path.resolve(__dirname, 'node_modules/casperjs/bin/casperjs')
const scraper = path.resolve(__dirname, 'scraper.js')
let isRunning = false
let lastRes
let lastFree
module.exports = function run () {
if (isRunning) {
return
}
isRunning = true
try {
const res = execFileSync(casper, ['--verbose', scraper]).toString()
const parsedRes = JSON.parse(res)
if (!lastRes || res !== lastRes) {
const free = parsedRes.reduce((sum, e) => sum + e.free, 0)
const notification = {
title: (lastRes ? 'Aktualisierte' : 'Aktuelle') + ' Standesamttermine',
message: free
? parsedRes.filter(e => e.free).map(e => `\n${e.day}.${e.month}.${e.year}: ${e.free}`).join(',')
: `Keine freien Termine${lastRes && lastFree ? ' mehr' : ''}`,
wait: true,
sound: true
}
notifier.notify(notification)
fs.writeFileSync(logFile, new Date() + ':' + notification.message.replace(/\n/g, '\n ') + '\n\n', {flag: 'a'})
lastFree = free
lastRes = res
}
} catch (e) {
console.error(e)
}
isRunning = false
}
{
"name": "standesamt-scraper",
"version": "1.0.0",
"description": "Scrape free dates for Standesamt Leipzig",
"main": "index.js",
"bin": "./standesamt-scraper",
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"casperjs": "^1.1.4",
"node-notifier": "^5.4.0"
}
}
const casper = require('casper').create()
casper
.start('https://tnv.leipzig.de/tnv/')
// Splash
.thenClick('#agreement_accept')
.thenClick('#action_infopage_next')
// Ämterauswahl
.waitForText('Standesamt')
.then(function () {
this.clickLabel(' Standesamt', 'button')
})
.waitForText('Termin vereinbaren')
.then(function () {
this.clickLabel('Termin vereinbaren', 'button')
})
// Auswahl des Anliegens
.waitForText('in Leipzig geboren', function () {
this.fillLabels('form', {
'Beurkundung von 2019 in Leipzig geborenen Kindern': '1'
})
this.click('#action_concernselect_next')
})
.waitForText('Zusatzinformationen zu den Anliegen', function () {
this.fillSelectors('form', {textarea: 'Foo'})
})
.thenClick('#action_concerncomments_next')
.waitForText('Auswahl des Termins', function () {
const dates = this.evaluate(function () {
const dates = []
const months = ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez']
try {
const tables = document.querySelectorAll('.ekolCalendarMonthTable')
Array.prototype.forEach.call(tables, function (table) {
const monthAndYear = table.querySelector('caption').innerText
const month = months.indexOf(monthAndYear.substr(0, 3)) + 1
const year = parseInt(monthAndYear.replace(/.+\s(20[0-9]{2,2})/, '$1'))
const buttons = table.querySelectorAll('.eKOLCalendarButtonDay')
Array.prototype.forEach.call(buttons, function (button) {
dates.push({
day: parseInt(button.querySelector('.ekolCalendarDayNumberInRange').innerText),
month: month,
year: year,
free: parseInt(button.querySelector('.ekolCalendarFreeTimeContainer').innerText.replace(' frei'))
})
})
})
} catch (e) {
__utils__.echo(e)
return null
}
return dates
})
if (dates) {
console.log(JSON.stringify(dates))
}
})
.run()
#!/usr/bin/env node
const scrape = require('../index')
scrape()
setInterval(scrape, 5 * 60 * 1000)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment