mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-03 11:07:00 -04:00
111 lines
3.8 KiB
TypeScript
111 lines
3.8 KiB
TypeScript
import './setup.ts';
|
||
|
||
import fs from 'fs';
|
||
|
||
import * as Sentry from '@sentry/node';
|
||
import { createEvents } from 'ics';
|
||
import { JSDOM } from 'jsdom';
|
||
|
||
import { Day } from '../src/calendar/helpers.ts';
|
||
import type { MiastamaszerujaceEvent } from '../src/calendar/helpers.ts';
|
||
|
||
import mailer from './mailer.ts';
|
||
|
||
import { loadTranslator } from '~/server/data.ts';
|
||
|
||
const __dirname = new URL('.', import.meta.url).pathname;
|
||
|
||
const year = Day.today().year;
|
||
|
||
const fetchEvents = async (): Promise<MiastamaszerujaceEvent[]> => {
|
||
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</a><br /><b>', 'g'), '</a></p><p><b>')
|
||
.replace(new RegExp('<span style="font-weight: 400;">(.*?)</span>', '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<void> => {
|
||
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);
|
||
},
|
||
);
|
||
})();
|