diff --git a/index.js b/index.js index 1bf7d75..675b46e 100644 --- a/index.js +++ b/index.js @@ -1,17 +1,13 @@ require('dotenv').config() -const express = require('express') const luxon = require('luxon'); const { WebUntis } = require('webuntis'); +const PocketBase = require('pocketbase/cjs'); -const app = express() -const port = process.env.PORT; +const pb = new PocketBase('https://fsae41.de'); -app.get('/', (req, res) => { - res.send('server is running') -}) - -app.get('/timetable', async (req, res) => { +async function getTimetabe() { const untis = new WebUntis(process.env.WEBUNTIS_SCHOOL, process.env.WEBUNTIS_USER, process.env.WEBUNTIS_PASS, process.env.WEBUNTIS_URL); + let timetable; try { await untis.login(); // Start und Ende der aktuellen Woche bestimmen @@ -21,33 +17,126 @@ app.get('/timetable', async (req, res) => { const endOfWeek = now.endOf('week').plus({ days: 7 * 4 * 4 }).toJSDate(); // Sonntag // Stundenplan für diese Woche abrufen - const timetable = await untis.getOwnTimetableForRange(startOfWeek, endOfWeek); + timetable = await untis.getOwnTimetableForRange(startOfWeek, endOfWeek); await untis.logout(); - res.json({ status: 'success', data: timetable }); } catch (error) { console.log(error); - res.statusCode = 500; - res.json({ status: 'error', message: error.message || error.toString() }); - } -}) - -const os = require('os'); -const nets = os.networkInterfaces(); -const results = {}; - -for (const name of Object.keys(nets)) { - for (const net of nets[name]) { - if (!net.internal) { - results[name] = results[name] || []; - results[name].push(net.address); - } } + return timetable; } -console.log('Local IPs:', results); + +setInterval(async () => { + const timetable = await getTimetabe(); + + if (!timetable || timetable.length === 0) { + console.log("No timetable data available."); + return; + } -app.listen(port, () => { - console.log(`Example app listening on port ${port}`) -}) \ No newline at end of file + let created = 0; + let updated = 0; + let skipped = 0; + + + const sorted = timetable.sort((a, b) => { + // Zuerst nach Datum + if (a.date !== b.date) { + return a.date - b.date; + } + // Falls Datum gleich, nach Startzeit + if (a.startTime !== b.startTime) { + return a.startTime - b.startTime; + } + // Falls Startzeit gleich, nach Endzeit + return a.endTime - b.endTime; + }); + + let final = [] + + for (let i = 0; i < sorted.length - 1; i++) { + let now = sorted[i]; + let next = sorted[i + 1]; + //gleicher tag + if (now.date == next.date) { + if (now.endTime == next.startTime) { + now.endTime = next.endTime; + final.push(now); + } + } + } + + pb.autoCancellation(false); + + const records = await pb.collection('classes').getFullList(); + //console.log(records); + + for (let i = 0; i < final.length; i++) { + let existingRecords; + + try { + existingRecords = await pb.collection('classes').getList(1, 0, { + filter: 'untis_id = "' + final[i].id + '"', + }); + existingRecords = existingRecords.items[0]; + } catch (error) { + } + //console.log(typeof existingRecords); + + + if (!existingRecords) { + // Neu erstellen + const data = { + "untis_id": final[i].id, + "date": final[i].date, + "startTime": final[i].startTime, + "endTime": final[i].endTime, + "ro": JSON.stringify(final[i].ro), + "su": JSON.stringify(final[i].su), + "kl": JSON.stringify(final[i].kl), + "raw": JSON.stringify(final[i]), + "old_version": "JSON" + }; + + const record = await pb.collection('classes').create(data); + created++; + continue; // Überspringe die Erstellung, wenn der Datensatz bereits existiert + } + + //console.log("Record with untis_id " + final[i].id + " already exists. Skipping creation."); + + // Prüfe, ob etwas geändert wurde + const isChanged = + existingRecords.date != final[i].date || + existingRecords.startTime != final[i].startTime || + existingRecords.endTime != final[i].endTime || + (existingRecords.kl[0].id != final[i].kl[0].id) || + (existingRecords.ro[0].id != final[i].ro[0].id) || + (existingRecords.su[0].id != final[i].su[0].id); + + if (!isChanged) { + skipped++; + continue; + } + + // Aktualisiere den bestehenden Datensatz + existingRecords.old_version = existingRecords.raw; + existingRecords.raw = JSON.stringify(final[i]); + existingRecords.date = final[i].date; + existingRecords.startTime = final[i].startTime; + existingRecords.endTime = final[i].endTime; + existingRecords.kl = final[i].kl; + existingRecords.ro = final[i].ro; + existingRecords.su = final[i].su; + existingRecords.last_update = new Date().toISOString(); + + const record = await pb.collection('classes').update(existingRecords.id, existingRecords); + + updated++; + } + + console.log(`✅ Sync done — Created: ${created}, Updated: ${updated}, Skipped: ${skipped}`); + +}, 1000 * 60 * 30); // Alle 30 Minuten aktualisieren \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7c065fc..8f0b225 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "dotenv": "^17.3.1", "express": "^5.2.1", "luxon": "^3.7.2", + "pocketbase": "^0.26.8", "webuntis": "^2.2.1" } }, @@ -796,6 +797,12 @@ "url": "https://opencollective.com/express" } }, + "node_modules/pocketbase": { + "version": "0.26.8", + "resolved": "https://registry.npmjs.org/pocketbase/-/pocketbase-0.26.8.tgz", + "integrity": "sha512-aQ/ewvS7ncvAE8wxoW10iAZu6ElgbeFpBhKPnCfvRovNzm2gW8u/sQNPGN6vNgVEagz44kK//C61oKjfa+7Low==", + "license": "MIT" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", diff --git a/package.json b/package.json index 285b60b..7cb65eb 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "dotenv": "^17.3.1", "express": "^5.2.1", "luxon": "^3.7.2", + "pocketbase": "^0.26.8", "webuntis": "^2.2.1" } }