Files
aphp-gestime-exporter/src/utils/data.ts

131 lines
3.1 KiB
TypeScript

import type { IcsCalendar, IcsEvent } from "ts-ics";
import { isPlanningUrl } from "./url";
type WorkEvent = {
day: number;
start: { hours: number; minutes: number };
end: { hours: number; minutes: number };
};
const makeIcsEvent = (
data: {
year: number;
month: number;
} & WorkEvent,
): IcsEvent => ({
uid: `${data.year}-${data.month}-${data.day}-work@aphp-gestime-exporter`,
summary: "Travail",
stamp: { date: new Date() },
start: {
// - 1 because Date takes month index, e.g 0-11
date: new Date(
data.year,
data.month - 1,
data.day,
data.start.hours,
data.start.minutes,
),
},
duration: {
hours: Math.floor(
(data.end.hours * 60 +
data.end.minutes -
(data.start.hours * 60 + data.start.minutes)) /
60,
),
minutes:
(data.end.hours * 60 +
data.end.minutes -
(data.start.hours * 60 + data.start.minutes)) %
60,
},
location: "Hôpital Pitié-Salpêtrière",
});
const makeIcsCalendar = (events: IcsEvent[]): IcsCalendar => ({
version: "2.0",
prodId: "-//pihkaal//Gestime APHP Export//FR",
events,
});
const dataExtractor = () => {
// extract year and month
const monthSelect = document.getElementById(
"select-pagemois",
) as HTMLSelectElement;
const yearSelect = document.getElementById(
"select-pagean",
) as HTMLSelectElement;
// extract events
const trs = document.querySelectorAll("#clearfix-individuel table tr");
const events: WorkEvent[] = [];
// [Sam 01, RH]
// [Dim 02, 7:00 - 19:00]
for (const tr of trs) {
const tds = tr.querySelectorAll("td");
const dateText = tds[0]?.textContent?.trim() ?? "";
const dateMatch = dateText.match(/^[A-Z][a-z]{2}\s+(\d{2})$/);
if (!dateMatch) continue;
const workText = tds[1]?.textContent?.trim() ?? "";
const hoursMatch = workText.match(/^(\d+):(\d+) - (\d+):(\d+)$/);
if (!hoursMatch) continue;
events.push({
day: parseInt(dateMatch[1]!),
start: {
hours: parseInt(hoursMatch[1]!),
minutes: parseInt(hoursMatch[2]!),
},
end: {
hours: parseInt(hoursMatch[3]!),
minutes: parseInt(hoursMatch[4]!),
},
});
}
return {
month: parseInt(monthSelect.value),
year: parseInt(yearSelect.value),
events,
};
};
export async function extractData(): Promise<{
name: string;
data: IcsCalendar;
}> {
const [tab] = await chrome.tabs.query({
active: true,
currentWindow: true,
});
if (!tab?.id || !(await isPlanningUrl())) {
throw new Error("URL incorrecte");
}
try {
const [query] = await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: dataExtractor,
});
if (!query?.result) throw undefined;
const { year, month, events } = query.result;
return {
name: `gestime-${year}-${month}.ics`,
data: makeIcsCalendar(
events.map((event) => makeIcsEvent({ year, month, ...event })),
),
};
} catch {
throw new Error(
"Impossible d'extraires les données, contactez `hello@pihkaal.me`",
);
}
}