#!/usr/bin/env node // Peakz Padel beschikbaarheid scraper // Aanroep: node padel-peakz.mjs [datum] [locatie] // Voorbeeld: node padel-peakz.mjs 2026-05-24 Atoomweg const { chromium } = require('playwright'); const LOCATIONS = { 'Atoomweg': '6637dd8e-cd4b-4fee-af49-196f6828b7dc', 'Groningen': '6637dd8e-cd4b-4fee-af49-196f6828b7dc', }; const RESERVATION_TYPE = '6'; const PLAYING_TIME = '90'; async function getAvailability(dateStr, locationName) { const locationId = LOCATIONS[locationName] || LOCATIONS['Atoomweg']; const browser = await chromium.launch({ headless: true }); const context = await browser.newContext({ userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36' }); const page = await context.newPage(); try { const url = `https://www.peakzpadel.nl/reserveren/court-booking/reservation?daypart=---&date=${dateStr}&location=${encodeURIComponent(locationName)}&playingTimes=${PLAYING_TIME}&courtTypeIds=13`; await page.goto(url, { waitUntil: 'networkidle', timeout: 30000 }); await page.waitForTimeout(3000); const slots = await page.evaluate(() => { const buttons = document.querySelectorAll('button'); const results = []; for (const btn of buttons) { const text = btn.textContent.trim(); if (text.match(/^\d{2}:\d{2}/)) { const price = text.match(/€\s*([\d,]+)/); results.push({ time: text.split(' ')[0], price: price ? price[1] : null, available: !btn.disabled }); } } return results; }); return { date: dateStr, location: locationName, slots, available: slots.filter(s => s.available), unavailable: slots.filter(s => !s.available) }; } catch (err) { return { error: err.message }; } finally { await browser.close(); } } // CLI mode const dateArg = process.argv[2] || new Date().toISOString().split('T')[0]; const locationArg = process.argv[3] || 'Atoomweg'; getAvailability(dateArg, locationArg).then(result => { if (result.error) { console.error('Fout:', result.error); process.exit(1); } // Output als JSON voor machine-readable if (process.argv.includes('--json')) { console.log(JSON.stringify(result)); process.exit(0); } // Human readable const dayNames = ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za']; const d = new Date(result.date); const dayLabel = dayNames[d.getDay()]; const dateLabel = `${dayLabel} ${d.getDate()}/${d.getMonth()+1}`; console.log(`\nšŸ“ Peakz Padel — ${result.location}`); console.log(`šŸ“… ${dateLabel}`); console.log(`🟢 ${result.available.length} banen vrij`); console.log(`šŸ”“ ${result.unavailable.length} banen bezet`); console.log(''); if (result.available.length > 0) { console.log('Vrije tijden:'); for (const s of result.available) { const price = s.price ? ` — €${s.price}` : ''; console.log(` 🟢 ${s.time}${price}`); } } console.log(''); process.exit(0); });