Compare commits

...

7 Commits

3 changed files with 101 additions and 59 deletions

View File

@ -4,23 +4,43 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calendar Merger</title> <title>Calendar Merger</title>
<link rel="stylesheet" href="/styles.css"> <style>
body {
font-family: Arial, sans-serif;
}
#calendars {
margin-bottom: 20px;
}
#calendars .calendar {
margin-bottom: 10px;
}
#calendars .calendar input[type="text"] {
width: 50%;
margin-right: 10px;
}
#calendars .calendar input[type="url"] {
width: 50%;
}
#add-calendar {
margin-bottom: 20px;
}
</style>
</head> </head>
<body> <body>
<h1>Calendar Merger</h1> <h1>Calendar Merger</h1>
<form id="merge-form"> <form id="merge-form">
<label for="cal1-url">Calendar 1 URL:</label> <div id="calendars">
<input type="url" id="cal1-url" name="cal1-url"><br><br> <div class="calendar">
<label for="cal1-prefix">Calendar 1 Prefix:</label> <input type="text" id="prefix-0" placeholder="Prefix">
<input type="text" id="cal1-prefix" name="cal1-prefix"><br><br> <input type="url" id="url-0" placeholder="Calendar URL">
<label for="cal2-url">Calendar 2 URL:</label> </div>
<input type="url" id="cal2-url" name="cal2-url"><br><br> </div>
<label for="cal2-prefix">Calendar 2 Prefix:</label> <button id="add-calendar" type="button">Add Calendar</button>
<input type="text" id="cal2-prefix" name="cal2-prefix"><br><br>
<button type="submit">Merge Calendars</button> <button type="submit">Merge Calendars</button>
</form> </form>
<div id="result"></div> <div id="result"></div>
<script src="script.js"></script> <script src="script.js"></script>
</body> </body>
</html> </html>

View File

@ -1,31 +1,42 @@
const form = document.getElementById('merge-form'); const form = document.getElementById('merge-form');
const resultDiv = document.getElementById('result'); const calendars = document.getElementById('calendars');
const addCalendarButton = document.getElementById('add-calendar');
const result = document.getElementById('result');
form.addEventListener('submit', (e) => { let calendarIndex = 1;
e.preventDefault();
const cal1Url = document.getElementById('cal1-url').value;
const cal1Prefix = document.getElementById('cal1-prefix').value;
const cal2Url = document.getElementById('cal2-url').value;
const cal2Prefix = document.getElementById('cal2-prefix').value;
fetch('/merge', { addCalendarButton.addEventListener('click', () => {
method: 'POST', const newCalendar = document.createElement('div');
headers: { newCalendar.className = 'calendar';
'Content-Type': 'application/json' newCalendar.innerHTML = `
}, <input type="text" id="prefix-${calendarIndex}" placeholder="Prefix">
body: JSON.stringify({ <input type="url" id="url-${calendarIndex}" placeholder="Calendar URL">
cal1Url, `;
cal1Prefix, calendars.appendChild(newCalendar);
cal2Url, calendarIndex++;
cal2Prefix });
})
}) form.addEventListener('submit', (event) => {
.then(response => response.json()) event.preventDefault();
.then((data) => { const calendarsData = [];
resultDiv.innerHTML = `Merged calendar URL: <a href="${data.url}" target="_blank">${data.url}</a>`; for (let i = 0; i < calendarIndex; i++) {
}) const prefix = document.getElementById(`prefix-${i}`).value;
.catch((error) => { const url = document.getElementById(`url-${i}`).value;
console.error(error); calendarsData.push({ prefix, url });
resultDiv.innerHTML = 'Error merging calendars'; }
}); fetch('/merge', {
}); method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ calendars: calendarsData })
})
.then((response) => response.json())
.then((data) => {
result.innerHTML = `Merged calendar URL: <a href="${data.url}">${data.url}</a>`;
})
.catch((error) => {
console.error(error);
result.innerHTML = 'Error merging calendars';
});
});

View File

@ -14,36 +14,46 @@ app.get('/', (req, res) => {
}); });
app.post('/merge', async (req, res) => { app.post('/merge', async (req, res) => {
const { cal1Url, cal1Prefix, cal2Url, cal2Prefix } = req.body; const { calendars } = req.body;
try { try {
//validate the input
if (!calendars || !Array.isArray(calendars)) {
return res.status(400).json({ error: 'Invalid input' });
}
// Fetch calendar data from URLs // Fetch calendar data from URLs
const cal1Data = await axios.get(cal1Url); const promises = calendars.map((calendar) => {
const cal2Data = await axios.get(cal2Url); return axios.get(calendar.url)
.then((response) => {
return {
data: response.data,
prefix: calendar.prefix,
};
})
.catch((error) => {
console.error(error);
return null;
});
});
const results = await Promise.all(promises);
// Filter out any failed requests
const validResults = results.filter((result) => result !== null);
// Parse calendar data // Parse calendar data
const cal1 = ical.parseICS(cal1Data.data);
const cal2 = ical.parseICS(cal2Data.data);
const mergedCal = []; const mergedCal = [];
validResults.forEach((result) => {
// Merge calendars const calendar = ical.parseICS(result.data);
Object.keys(cal1).forEach((key) => { Object.keys(calendar).forEach((key) => {
let event = cal1[key]; const event = calendar[key];
mergedCal.push({ mergedCal.push({
start: event.start, start: event.start,
end: event.end, end: event.end,
summary: `${cal1Prefix} ${event.summary}`, summary: `${result.prefix} ${event.summary}`,
});
}); });
}); });
Object.keys(cal2).forEach((key) => {
let event = cal2[key];
mergedCal.push({
start: event.start,
end: event.end,
summary: `${cal2Prefix} ${event.summary}`,
});
});
// Save merged calendar to file // Save merged calendar to file
const filename = `merged-${Date.now()}.ics`; const filename = `merged-${Date.now()}.ics`;
@ -63,6 +73,7 @@ END:VEVENT
icalString += `END:VCALENDAR`; icalString += `END:VCALENDAR`;
fs.writeFileSync(filename, icalString); fs.writeFileSync(filename, icalString);
// Generate a unique URL for the merged calendar // Generate a unique URL for the merged calendar
const mergedCalendarUrl = `${req.protocol}://${req.get('host')}/${filename}`; const mergedCalendarUrl = `${req.protocol}://${req.get('host')}/${filename}`;