Compare commits

...

7 Commits
1.0.0 ... main

7 changed files with 78 additions and 18 deletions

3
.gitignore vendored
View File

@ -1 +1,2 @@
node_modules node_modules
test.js

View File

@ -12,7 +12,7 @@ npm install virtueller-stundenplan
# Note # Note
This project in **very early developement**, expect things to break and change. This project in (relatively) early developement, expect some things to break and change.
# Usage # Usage

View File

@ -1,4 +1,5 @@
const crypto = require('node:crypto'); const crypto = require('node:crypto');
const { DateTime } = require('luxon');
class EncryptionHelper { class EncryptionHelper {
static encryptDataAESGCM(plainText, key) { static encryptDataAESGCM(plainText, key) {
@ -17,8 +18,9 @@ class EncryptionHelper {
} }
static makeEncryptedParameter(username, key) { static makeEncryptedParameter(username, key) {
const timestamp = new Date().toISOString().replace('T', ' ').split('.')[0]; const timestamp = DateTime.now().setZone('Europe/Berlin');
const plainText = `${timestamp} ${username}`; const tsFormatted = timestamp.toFormat('yyyy-MM-dd HH:mm:ss');
const plainText = `${tsFormatted} ${username}`;
const hash = crypto.createHash('sha256').update(key, 'utf8').digest(); const hash = crypto.createHash('sha256').update(key, 'utf8').digest();
const encryptedData = this.encryptDataAESGCM(plainText, hash); const encryptedData = this.encryptDataAESGCM(plainText, hash);

View File

@ -13,7 +13,7 @@ class VirtuellerStundenplan {
this.#password = config.password; this.#password = config.password;
if(config.key) this.key = config.key; if(config.key) this.key = config.key;
//this.teacherList = config.teachers; this.holidays = config.holidays;
} }
async fetchKey(returnKey=false) { async fetchKey(returnKey=false) {
@ -53,6 +53,19 @@ class VirtuellerStundenplan {
}; };
} }
/**
* Returns all classes of the school.
*
* @returns {String[]}
*/
async getClassList() {
const data = await this.request("RESTKlassenliste.php");
return {
head: new Head(data.Msg),
content: data.Klassen,
};
}
/** /**
* Returns all Messages. * Returns all Messages.
* *
@ -189,7 +202,7 @@ class VirtuellerStundenplan {
const hasContent = /[\da-zA-Z]/.test(JSON.stringify(day)); const hasContent = /[\da-zA-Z]/.test(JSON.stringify(day));
res.content[i] = hasContent ? new TimetableDay(day) : null; res.content[i] = hasContent ? new TimetableDay(day, this.holidays) : null;
} }
return res; return res;

View File

@ -3,12 +3,11 @@ const TimetableHour = require("./TimetableHour");
class TimetableDay { class TimetableDay {
first = null; first = null;
last = null; last = null;
holiday = false;
constructor(data) { constructor(data, holidays=defaultHolidays) {
this.hours = []; this.hours = [];
//console.log(data)
for (let i = 0; i < data[0].length; i++) { for (let i = 0; i < data[0].length; i++) {
const hour = [ const hour = [
data[0][i], data[0][i],
@ -16,7 +15,14 @@ class TimetableDay {
data[2][i], data[2][i],
data[3][i], data[3][i],
data[4][i], data[4][i],
] ];
const allSame = sameHours(data);
if(holidays.includes(allSame)) {
this.holiday = allSame;
return;
}
const hasContent = /[\da-zA-Z]/.test(JSON.stringify(hour)); const hasContent = /[\da-zA-Z]/.test(JSON.stringify(hour));
@ -28,6 +34,44 @@ class TimetableDay {
this.hours[i] = hasContent ? new TimetableHour(hour) : null; this.hours[i] = hasContent ? new TimetableHour(hour) : null;
} }
} }
get isHoliday() {
return this.holiday !== false;
}
get holidayName() {
return this.isHoliday ? this.holiday : null;
}
} }
/**
* Checks if the day only has the same hours (e.g. "-", "Himmelfahrt")
*
* @param {Array} day (Nested) Day as an array.
* @returns {false|string} False if they differ. When not it returns the only existing value.
*/
const sameHours = day => {
// Only include column teacher, subject and room.
// Exam always "-", except for when there's exams.
day = [day[0], day[1], day[2]];
const flat = day.flat(); // from [["x","x"]] to ["x","x"]
const first = flat[0];
return flat.every(val => val === first) ? first : false;
};
const defaultHolidays = [
"Sommerferien",
"Tag der Deutschen Einheit",
"Herbstferien",
"Reformationstag",
"Weihnachtsferien",
"Winterferien",
"Osterferien",
"Tag der Arbeit",
"Himmelfahrt",
"Pfingsten",
];
module.exports = TimetableDay; module.exports = TimetableDay;

12
npm-shrinkwrap.json generated
View File

@ -1,16 +1,16 @@
{ {
"name": "virtueller-stundenplan", "name": "virtueller-stundenplan",
"version": "1.0.0", "version": "1.2.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "virtueller-stundenplan", "name": "virtueller-stundenplan",
"version": "1.0.0", "version": "1.2.0",
"license": "CC-BY-NC-4.0", "license": "CC-BY-NC-4.0",
"dependencies": { "dependencies": {
"axios": "^1.8.4", "axios": "^1.8.4",
"luxon": "^3.5.0" "luxon": "^3.6.1"
} }
}, },
"node_modules/asynckit": { "node_modules/asynckit": {
@ -256,9 +256,9 @@
} }
}, },
"node_modules/luxon": { "node_modules/luxon": {
"version": "3.5.0", "version": "3.6.1",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.6.1.tgz",
"integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", "integrity": "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=12" "node": ">=12"

View File

@ -1,6 +1,6 @@
{ {
"name": "virtueller-stundenplan", "name": "virtueller-stundenplan",
"version": "1.0.0", "version": "1.2.0",
"description": "A library to access the data from virtueller-stundenplan.org", "description": "A library to access the data from virtueller-stundenplan.org",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@ -19,6 +19,6 @@
"license": "CC-BY-NC-4.0", "license": "CC-BY-NC-4.0",
"dependencies": { "dependencies": {
"axios": "^1.8.4", "axios": "^1.8.4",
"luxon": "^3.5.0" "luxon": "^3.6.1"
} }
} }