219 lines
6.0 KiB
TypeScript
219 lines
6.0 KiB
TypeScript
const fetch = require('node-fetch');
|
|
|
|
export const getiCalFile = async (user: string, file: string, showBlockers: boolean, electiveModule: string, profileModule: string): Promise<string> => {
|
|
try {
|
|
let iCalFileContents = '';
|
|
|
|
let baseUrl = 'https://rapla.dhbw-karlsruhe.de/rapla?page=ical';
|
|
baseUrl += '&user=' + user;
|
|
baseUrl += '&file=' + file;
|
|
|
|
const response = await fetch(baseUrl);
|
|
|
|
let body = await response.text();
|
|
|
|
// Parse the ical file
|
|
let iCalFile = parseIcal(body);
|
|
|
|
// Now remove unwanted shit from the iCal file
|
|
if (!showBlockers) {
|
|
iCalFile = removeBlockers(iCalFile);
|
|
}
|
|
|
|
if (electiveModule !== '') {
|
|
iCalFile = removeElective(iCalFile, electiveModule);
|
|
}
|
|
|
|
if (profileModule !== '') {
|
|
iCalFile = removeProfile(iCalFile, profileModule);
|
|
}
|
|
|
|
// Turn into one file again
|
|
let resultingFile = serializeIcal(iCalFile);
|
|
|
|
return resultingFile;
|
|
} catch (err) {
|
|
throw err;
|
|
}
|
|
};
|
|
|
|
export const parseIcal = function (icalContents: string): iCalFile {
|
|
const fileHeaderRegex: RegExp = /^BEGIN:VCALENDAR.*?BEGIN:VEVENT$/ms;
|
|
const eventRegex: RegExp = /^BEGIN:VEVENT.*?END:VEVENT$/msg;
|
|
|
|
let headerMatch = fileHeaderRegex.exec(icalContents);
|
|
let header = '';
|
|
|
|
if (headerMatch) {
|
|
header = headerMatch[0];
|
|
}
|
|
|
|
header = header.substr(0, header.lastIndexOf('\n') + 1);
|
|
|
|
let events: iCalEvent[] = [];
|
|
let match: any;
|
|
while (match = eventRegex.exec(icalContents)) {
|
|
if (match) {
|
|
events.push({
|
|
content: match[0],
|
|
duration: getDuration(match[0])
|
|
});
|
|
}
|
|
}
|
|
|
|
return {
|
|
head: header,
|
|
body: events
|
|
};
|
|
};
|
|
|
|
export const getDuration = function (event: string): number {
|
|
let startRegex: RegExp = /DTSTART.*?(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z?\r/gm;
|
|
let endRegex: RegExp = /DTEND.*?(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z?\r/gm;
|
|
|
|
let startMatch = startRegex.exec(event);
|
|
|
|
let startDtYear = 0;
|
|
let startDtMonth = 0;
|
|
let startDtDay = 0;
|
|
let startDtHour = 0;
|
|
let startDtMinute = 0;
|
|
if (startMatch) {
|
|
startDtYear = parseInt(startMatch[1]);
|
|
startDtMonth = parseInt(startMatch[2]);
|
|
startDtDay = parseInt(startMatch[3]);
|
|
startDtHour = parseInt(startMatch[4]);
|
|
startDtMinute = parseInt(startMatch[5]);
|
|
}
|
|
|
|
let endMatch = endRegex.exec(event);
|
|
let endDtYear = 0;
|
|
let endDtMonth = 0;
|
|
let endDtDay = 0;
|
|
let endDtHour = 0;
|
|
let endDtMinute = 0;
|
|
if (endMatch) {
|
|
endDtYear = parseInt(endMatch[1]);
|
|
endDtMonth = parseInt(endMatch[2]);
|
|
endDtDay = parseInt(endMatch[3]);
|
|
endDtHour = parseInt(endMatch[4]);
|
|
endDtMinute = parseInt(endMatch[5]);
|
|
}
|
|
|
|
let startDt = new Date(startDtYear, startDtMonth - 1, startDtDay, startDtHour, startDtMinute);
|
|
let endDt = new Date(endDtYear, endDtMonth - 1, endDtDay, endDtHour, endDtMinute);
|
|
|
|
let hourDifference = endDt.getHours() - startDt.getHours();
|
|
let minuteDifference = 0;
|
|
|
|
if (hourDifference === 0) {
|
|
minuteDifference = endDt.getMinutes() - startDt.getMinutes();
|
|
}
|
|
|
|
return hourDifference + (minuteDifference / 60);
|
|
};
|
|
|
|
export const serializeIcal = function (ical: iCalFile): string {
|
|
let resString = ical.head;
|
|
ical.body.forEach((event) => {
|
|
resString += event.content + '\n';
|
|
});
|
|
resString += 'END:VCALENDAR\n';
|
|
|
|
return resString;
|
|
};
|
|
|
|
export const removeBlockers = function (ical: iCalFile): iCalFile {
|
|
let remainingEvents: iCalEvent[] = [];
|
|
|
|
ical.body.forEach((event) => {
|
|
if (
|
|
!event.content.includes('SUMMARY:Beginn Theorie')
|
|
&& !event.content.includes('SUMMARY:Präsenz')
|
|
&& event.duration < 10
|
|
&& event.duration > 0.25
|
|
) {
|
|
remainingEvents.push(event);
|
|
}
|
|
});
|
|
|
|
ical.body = remainingEvents;
|
|
|
|
return ical;
|
|
};
|
|
|
|
export const removeElective = function (ical: iCalFile, chosenElective: string): iCalFile {
|
|
let remainingEvents: iCalEvent[] = [];
|
|
|
|
let electiveToRemove = [
|
|
{name: 'ERP-Systeme'},
|
|
{name: 'Ethik für Informatiker'},
|
|
{name: 'Evolutionäre Algorithmen'},
|
|
{name: 'Forensik'},
|
|
{name: 'Kryptographische Verfahren'},
|
|
{name: 'Robotik'},
|
|
{name: 'Web-Services'},
|
|
{name: 'High Performance Computing'}
|
|
];
|
|
electiveToRemove.splice(parseInt(chosenElective), 1);
|
|
|
|
ical.body.forEach((event) => {
|
|
let addEvent = true;
|
|
electiveToRemove.forEach((module) => {
|
|
if (event.content.includes(module.name)) {
|
|
addEvent = false;
|
|
}
|
|
});
|
|
|
|
if (addEvent) {
|
|
remainingEvents.push(event);
|
|
}
|
|
});
|
|
|
|
ical.body = remainingEvents;
|
|
|
|
return ical;
|
|
};
|
|
|
|
export const removeProfile = function (ical: iCalFile, chosenProfile: string): iCalFile {
|
|
let remainingEvents: iCalEvent[] = [];
|
|
|
|
let profileToRemove = [
|
|
{names: ['.Grundlagen der KI (KI und BV)', 'Bildverarbeitung (KI und BV)']},
|
|
{names: ['Bildverarbeitung', 'Computergraphik']},
|
|
{names: ['Interaktive Systeme', 'Grundlagen der KI']},
|
|
{names: ['e Business', 'angewandtes Projektmanagement']},
|
|
{names: ['Kommunikations und Netztechnik II']}
|
|
];
|
|
profileToRemove.splice(parseInt(chosenProfile), 1);
|
|
|
|
ical.body.forEach((event) => {
|
|
let addEvent = true;
|
|
profileToRemove.forEach((module) => {
|
|
module.names.forEach((name) => {
|
|
if (event.content.includes(name)) {
|
|
addEvent = false;
|
|
}
|
|
});
|
|
});
|
|
|
|
if (addEvent) {
|
|
remainingEvents.push(event);
|
|
}
|
|
});
|
|
|
|
ical.body = remainingEvents;
|
|
|
|
return ical;
|
|
};
|
|
|
|
export interface iCalFile {
|
|
head: string;
|
|
body: iCalEvent[];
|
|
}
|
|
|
|
export interface iCalEvent {
|
|
content: string;
|
|
duration: number; // Duration in hours
|
|
}
|