import './setup.ts'; import fs from 'fs'; import * as Sentry from '@sentry/node'; import { createEvents } from 'ics'; import { JSDOM } from 'jsdom'; import mailer from './mailer.ts'; import { Day } from '#shared/calendar/helpers.ts'; import type { MiastamaszerujaceEvent } from '#shared/calendar/helpers.ts'; import { loadTranslator } from '~~/server/data.ts'; const __dirname = new URL('.', import.meta.url).pathname; const year = Day.today().year; const fetchEvents = async (): Promise => { const events: MiastamaszerujaceEvent[] = []; // issue with third-party cert: Verification error: unable to verify the first certificate // browser and curl accepts the certificate, but node seems more picky process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; const html = await (await fetch('https://miastamaszerujace.pl/')).text(); const dom = new JSDOM(html // manual fixes for irregular HTML .replace(new RegExp('ref=newsfeed
', 'g'), '

') .replace(new RegExp('(.*?)', 'g'), '$1')); const eventNodes = dom.window.document.querySelectorAll('[data-id="d4c3075"] p, [data-id="9cc25f4"] p'); for (const p of eventNodes) { if (p.textContent!.includes('Daty kolejnych') || p.textContent!.includes('Marsz organizowany przez grupę współpracującą') || p.textContent!.includes('Opublikowane do tej pory') ) { continue; } const [day, month] = p.querySelector('b,strong')!.textContent!.trim().split('/'); const date = new Day(year, parseInt(month), parseInt(day)); const name = [...p.childNodes] .filter((c) => c.nodeType === 3 /* text node */ || c.nodeName === 'A') .map((c) => c.textContent!.trim()) .filter((t) => !!t) .join(' ') .replace(/^– /, '') ; let link = null; try { link = new URL(p.querySelector('a')!.getAttribute('href')!); link.hash = ''; link.search = ''; } catch (e) { void 0; } events.push({ name, date, link: link ? link.toString() : null, }); } return events; }; (async (): Promise => { const events = await fetchEvents(); console.log(events); const dir = `${__dirname}/../calendar/pl`; const path = `${dir}/miastamaszerujace-${year}.json`; const previous = fs.existsSync(path) ? JSON.parse(fs.readFileSync(path).toString('utf-8')) : []; if (JSON.stringify(events) !== JSON.stringify(previous)) { console.log('wykryto zmiany, wysyłam maila'); await mailer('kontakt@zaimki.pl', 'miastamaszerujace', await loadTranslator('_'), { before: JSON.stringify(previous, null, 4), after: JSON.stringify(events, null, 4), maxwidth: '100%', }); } if (previous.length > events.length) { console.error('stopping execution, number of events decreased'); return; } console.log(`Saving to ${path}`); fs.writeFileSync(path, JSON.stringify(events, null, 4)); createEvents( events.map((e, i) => { return { title: e.name, start: [e.date.year, e.date.month, e.date.day], end: [e.date.year, e.date.month, e.date.day], calName: `Marsze Równości ${year}`, sequence: i, }; }), (error, value) => { if (error) { Sentry.captureException(error); return; } console.log(`Saving to ${dir}/miastamaszerujace.ics`); fs.writeFileSync(`${dir}/miastamaszerujace.ics`, value); }, ); })();