Big Update
This commit is contained in:
@@ -1,110 +1,269 @@
|
||||
const axios = require("axios");
|
||||
const EncryptionHelper = require("./EncryptionHelper");
|
||||
|
||||
const { Head, Functions, Message, Homework, SchoolYear, TimetableDay, AbsentSummary } = require("./parsers");
|
||||
|
||||
class VirtuellerStundenplan {
|
||||
baseUrl = "https://virtueller-stundenplan.de/Reservierung/";
|
||||
|
||||
constructor(username, password, key) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
if(key) this.key = key;
|
||||
#password;
|
||||
|
||||
constructor(config) {
|
||||
this.username = config.username;
|
||||
this.#password = config.password;
|
||||
if(config.key) this.key = config.key;
|
||||
|
||||
//this.teacherList = config.teachers;
|
||||
}
|
||||
|
||||
async fetchKey(returnKey=false) {
|
||||
const url = new URL("RestGetKeyphrase.php", this.baseUrl);
|
||||
|
||||
try {
|
||||
const req = await axios(url.href, {
|
||||
headers: {
|
||||
Authorization: "Basic " + Buffer.from(this.username + ":" + this.password).toString('base64'),
|
||||
},
|
||||
});
|
||||
const req = await axios(url.href, {
|
||||
headers: {
|
||||
Authorization: "Basic " + Buffer.from(this.username + ":" + this.#password).toString('base64'),
|
||||
},
|
||||
});
|
||||
|
||||
this.key = req.data.KeyPhrase;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
this.key = req.data.KeyPhrase;
|
||||
|
||||
return returnKey ? this.key : true;
|
||||
}
|
||||
|
||||
async getEnabledFunctions() {
|
||||
return await this.request("RESTEnabledFunctions.php");
|
||||
/**
|
||||
* Returns all enabled and disabled functions.
|
||||
*
|
||||
* @returns {Functions}
|
||||
*/
|
||||
async getFunctions() {
|
||||
return new Functions(await this.request("RESTEnabledFunctions.php"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns something with Courses.
|
||||
* This Response is currently unparsed.
|
||||
*
|
||||
* @returns {Any[]}
|
||||
*/
|
||||
async getCourseList() {
|
||||
return await this.request("RESTKursliste.php");
|
||||
const data = await this.request("RESTKursliste.php");
|
||||
return {
|
||||
head: new Head(data.Msg),
|
||||
content: data.Kurse,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all Messages.
|
||||
*
|
||||
* @returns {Message[]}
|
||||
*/
|
||||
async getMessages() {
|
||||
return await this.request("RESTMessages.php");
|
||||
const data = await this.request("RESTMessages.php");
|
||||
let res = [];
|
||||
data.Messages.forEach(message => {
|
||||
res.push(new Message(message));
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* getHomework response
|
||||
*
|
||||
* @typedef {Object} getHomeworkResponse
|
||||
* @property {Head} head - Info to the response
|
||||
* @property {Homework[]} content
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns all Homework (Classbook) entries.
|
||||
* Date arguments are inclusive.
|
||||
*
|
||||
* @param {String|Date} from
|
||||
* @param {String|Date} to
|
||||
* @returns {Object}
|
||||
* @param {[String|Date|number]} [from=Date.now()] - First Day
|
||||
* @param {[String|Date|number]} [to=Date.now()] - Last Day
|
||||
* @returns {getHomeworkResponse} getHomework response
|
||||
*/
|
||||
async getHomework(from=new Date(), to=new Date()) {
|
||||
const query = new URLSearchParams();
|
||||
query.set("KlaBuDateVon", this.getDateString(from));
|
||||
query.set("KlaBuDateBis", this.getDateString(to));
|
||||
return await this.request("RESTHausaufgaben.php", query);
|
||||
}
|
||||
|
||||
async getSchoolYears() {
|
||||
return await this.request("RESTSchuljahre.php");
|
||||
const data = await this.request("RESTHausaufgaben.php", query);
|
||||
|
||||
let res = {
|
||||
head: new Head(data.Msg),
|
||||
content: [],
|
||||
};
|
||||
data.Inhalte.forEach(homework => {
|
||||
res.content.push(new Homework(homework));
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* getSchoolYears response
|
||||
*
|
||||
* @param {string|number} schoolYear ID of the school year
|
||||
* @returns
|
||||
* @typedef {Object} getSchoolYearsResponse
|
||||
* @property {Head} head - Info to the response
|
||||
* @property {SchoolYear[]} content
|
||||
*/
|
||||
/**
|
||||
* Returns all school years.
|
||||
*
|
||||
* @returns {getSchoolYearsResponse} getSchoolYears response
|
||||
*/
|
||||
async getSchoolYears() {
|
||||
const data = await this.request("RESTSchuljahre.php");
|
||||
let res = {
|
||||
head: new Head(data.Msg),
|
||||
content: [],
|
||||
};
|
||||
data.Schuljahre.forEach(year => {
|
||||
res.content.push(new SchoolYear(year));
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns own grades (performances).
|
||||
* The response is currently mostly unparsed
|
||||
*
|
||||
* @param {string|number} schoolYear ID of the school year.
|
||||
* @returns {Object} response
|
||||
* @returns {Head} response.head - Info to the response
|
||||
* @returns {Object} response.content
|
||||
*/
|
||||
async getMyGrades(schoolYear) {
|
||||
const query = new URLSearchParams();
|
||||
query.set("SJ", schoolYear);
|
||||
return await this.request("RESTMeineNoten.php", query);
|
||||
const data = await this.request("RESTMeineNoten.php", query);
|
||||
|
||||
return {
|
||||
head: new Head(data.Msg),
|
||||
content: {
|
||||
performances: data.Leistungen,
|
||||
totalPerformances: data.LeistungenGesamt,
|
||||
comment: data.Kommentar,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* getTimetable response
|
||||
*
|
||||
* @typedef {Object} getTimetableResponse
|
||||
* @property {Head} head - Info to the response
|
||||
* @property {TimetableDay[]} content
|
||||
*/
|
||||
/**
|
||||
* Returns own timetable.
|
||||
*
|
||||
* Small note: If you are in only one class, and want to
|
||||
* fetch it with the class name, the response head will
|
||||
* be slightly different -> has a bit less metadata
|
||||
*
|
||||
* @param {[String|Date|number]} [from=Date.now()] - Date or timestamp
|
||||
* @param {[String|Date|number]} [Class] - The class of which timetable should be fetched. unset/null to own timetable.
|
||||
* @returns {getTimetableResponse} getTimetable response
|
||||
*/
|
||||
async getTimetable(from=new Date(), Class=null) {
|
||||
const query = new URLSearchParams();
|
||||
query.set("KlaBuDateVon", this.getDateString(from));
|
||||
if(Class) query.set("KLASSE", Class);
|
||||
|
||||
const data = await this.request(Class ? "RESTKlassenStundenplan.php" : "RESTMeinStundenplan.php", query);
|
||||
|
||||
let res = {
|
||||
head: new Head(data.Msg),
|
||||
content: [],
|
||||
}
|
||||
|
||||
for (let i = 0; i < data.Stunden.length; i++) {
|
||||
const day = [
|
||||
data.Stunden[i],
|
||||
data.StundenF[i],
|
||||
data.StundenR[i],
|
||||
data.StundenK[i],
|
||||
data.CellStyles[i],
|
||||
];
|
||||
|
||||
const hasContent = /[\da-zA-Z]/.test(JSON.stringify(day));
|
||||
|
||||
res.content[i] = hasContent ? new TimetableDay(day) : null;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns own timetable.
|
||||
* This function is a alias of getTimetable(), but without the Class option
|
||||
*
|
||||
* @returns {getTimetableResponse} getTimetable response
|
||||
*/
|
||||
async getMyTimetable(from=new Date()) {
|
||||
const query = new URLSearchParams();
|
||||
query.set("KlaBuDateVon", this.getDateString(from));
|
||||
return await this.request("RESTMeinStundenplan.php", query);
|
||||
}
|
||||
|
||||
async getTimetable(Class, from=new Date()) {
|
||||
const query = new URLSearchParams();
|
||||
query.set("KlaBuDateVon", this.getDateString(from));
|
||||
query.set("KLASSE", Class);
|
||||
return await this.request("RESTKlassenStundenplan.php", query);
|
||||
return await this.getTimetable(from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns own Infos.
|
||||
* This Response is currently unparsed.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
async getMyInfos() {
|
||||
return await this.request("RESTSuSInfo.php");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns own profile picture.
|
||||
* The response is currently mostly unparsed
|
||||
*
|
||||
* @returns {Object} response
|
||||
* @returns {Head} response.head - Info to the response
|
||||
* @returns {Object} response.content
|
||||
*/
|
||||
async getMyPicture() {
|
||||
return await this.request("RESTSuSMeinBild.php");
|
||||
const data = await this.request("RESTSuSMeinBild.php");
|
||||
|
||||
return {
|
||||
head: new Head(data.Msg),
|
||||
content: {
|
||||
schoolName: data.Schulname,
|
||||
picture: data.Bild,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* BBS ID QR
|
||||
* Returns own BBS ID QR Code.
|
||||
* This Response is currently unparsed.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
async getMyBBSIDQR() {
|
||||
return await this.request("RESTBBSIDQR.php");
|
||||
}
|
||||
|
||||
/**
|
||||
* BBS GUID QR
|
||||
* Returns own BBS GUID QR Code.
|
||||
* This Response is currently unparsed.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
async getMyBBSGUID() {
|
||||
return await this.request("RESTBBSIDGUID.php");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports self as sick.
|
||||
*
|
||||
* This Request is untested.
|
||||
*
|
||||
* This Response is currently unparsed.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
async reportAsSick(from=new Date(), to=new Date()) {
|
||||
const query = new URLSearchParams();
|
||||
query.set("KlaBuDateVon", this.getDateString(from));
|
||||
@@ -112,20 +271,60 @@ class VirtuellerStundenplan {
|
||||
return await this.request("RESTSuSKrankmelden.php", query);
|
||||
}
|
||||
|
||||
/**
|
||||
* getAbsentDays response
|
||||
*
|
||||
* @typedef {Object} getAbsentDaysResponse
|
||||
* @property {Head} head - Info to the response
|
||||
* @property {AbsentSummary[]} content
|
||||
*/
|
||||
/**
|
||||
* Returns absent days.
|
||||
*
|
||||
* @param {[String|Date|number]} [from=Date.now()] - Date or timestamp
|
||||
* @param {[String|Date|number]} [to=Date.now()] - Date or timestamp
|
||||
* @returns {getAbsentDaysResponse} getAbsentDays response
|
||||
*/
|
||||
async getAbsentDays(from=new Date(), to=new Date()) {
|
||||
const query = new URLSearchParams();
|
||||
query.set("KlaBuDateVon", this.getDateString(from));
|
||||
query.set("KlaBuDateBis", this.getDateString(to));
|
||||
return await this.request("RESTFehltageliste.php", query);
|
||||
|
||||
const data = await this.request("RESTFehltageliste.php", query);
|
||||
|
||||
return {
|
||||
head: new Head(data.Msg),
|
||||
content: new AbsentSummary(data),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of exams.
|
||||
* The response is currently mostly unparsed
|
||||
*
|
||||
* @returns {Object} response
|
||||
* @returns {Head} response.head - Info to the response
|
||||
* @returns {Object[]} response.content
|
||||
*/
|
||||
async getExamList(from=new Date(), to=new Date()) {
|
||||
const query = new URLSearchParams();
|
||||
query.set("KlaBuDateVon", this.getDateString(from));
|
||||
query.set("KlaBuDateBis", this.getDateString(to));
|
||||
return await this.request("RESTKlausurliste.php", query);
|
||||
|
||||
const data = await this.request("RESTKlausurliste.php", query);
|
||||
|
||||
return {
|
||||
head: new Head(data.Msg),
|
||||
content: data.Klausuren,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes to notifications.
|
||||
* This Response is currently unparsed.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
async subscribeToNotifications(Token, Register, IOS) {
|
||||
const query = new URLSearchParams();
|
||||
query.set("Token", Token);
|
||||
@@ -141,6 +340,9 @@ class VirtuellerStundenplan {
|
||||
if(date instanceof Date) {
|
||||
return date.toISOString().slice(0, 10);
|
||||
}
|
||||
if(typeof date === "number") {
|
||||
return this.getDateString(new Date(date));
|
||||
}
|
||||
throw new Error(`"${date}" is not a valid type for date.`);
|
||||
}
|
||||
|
||||
@@ -157,16 +359,11 @@ class VirtuellerStundenplan {
|
||||
if(query) url.search = query.toString();
|
||||
url.searchParams.set("key", EncryptionHelper.makeEncryptedParameter(this.username, this.key));
|
||||
|
||||
let req;
|
||||
try {
|
||||
req = await axios(url.href, {
|
||||
headers: {
|
||||
Authorization: "Basic " + Buffer.from(this.username + ":" + this.password).toString('base64'),
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
const req = await axios(url.href, {
|
||||
headers: {
|
||||
Authorization: "Basic " + Buffer.from(this.username + ":" + this.#password).toString('base64'),
|
||||
},
|
||||
});
|
||||
|
||||
return req.data;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user