86 lines
2.6 KiB
JavaScript
86 lines
2.6 KiB
JavaScript
import axios from "axios";
|
|
import crypto from "node:crypto";
|
|
import { log } from "../logs.js";
|
|
|
|
/*
|
|
This BOLLE (https://bolle-software.de/) parser tries to download
|
|
the latest substitution plan HTML files from the "Pinnwand".
|
|
|
|
It uses the same API that the mobile app (v0.3.6) uses.
|
|
To get your login credentials you need to log into your BOLLE account
|
|
and register a new device in the settings (/einstellungen/geraete_personal).
|
|
Click on "Manuelle Logindaten Einblenden" and use "ID" as apiUser
|
|
and "Token" as apiKey. You need to make at least one request with
|
|
this API token before closing the registration window or else the
|
|
token will be invalidated immediately.
|
|
*/
|
|
|
|
// Files to download from the "Pinnwand"
|
|
const filenames = ["vp_heute", "vp_morgen"];
|
|
|
|
export class BolleClient {
|
|
constructor(bolleInstance, apiUser, apiKey) {
|
|
this.bolleInstance = bolleInstance;
|
|
this.apiUser = apiUser;
|
|
this.apiKey = apiKey;
|
|
}
|
|
|
|
async getFiles() {
|
|
try {
|
|
let contents = [];
|
|
for (let file of filenames) {
|
|
contents.push(await this.getFile(file));
|
|
}
|
|
return contents;
|
|
} catch (error) {
|
|
log("Parser / Bolle", "Error getting data: " + error);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
async getFile(filename) {
|
|
// Generate the BOLLE api payload
|
|
let payload = {
|
|
api_payload: JSON.stringify({
|
|
method: "vertretungsplan_html",
|
|
payload: { content: filename },
|
|
}),
|
|
};
|
|
// Generate request headers
|
|
let headers = this.buildRequestHeaders(payload.api_payload);
|
|
// Send the POST request
|
|
let response = await axios.post(this.getRequestUrl(), payload, {
|
|
headers,
|
|
});
|
|
// The server responds with a json object
|
|
// containing the base64 encoded html data
|
|
let base64 = response.data["html_base64"];
|
|
// Decode the base64 data using the latin1 (ISO 8859-1) character set
|
|
return Buffer.from(base64, "base64").toString("latin1");
|
|
}
|
|
getRequestUrl() {
|
|
// The API that the bolle mobile app uses is available at /app/basic
|
|
return `https://${this.bolleInstance}/app/basic`;
|
|
}
|
|
buildRequestHeaders(payload) {
|
|
// Bolle needs the sha1 hash of the payload
|
|
// to be set as the "b-hash" header
|
|
let hash = crypto.createHash("sha1");
|
|
hash.update(payload);
|
|
|
|
return {
|
|
Accept: "application/json",
|
|
// Set the auth headers
|
|
"X-Auth-User": this.apiUser,
|
|
"X-Auth-Token": this.apiKey,
|
|
"App-Version": "4",
|
|
// Set the hash
|
|
"B-Hash": hash.digest("hex"),
|
|
"Content-Type": "application/json",
|
|
Connection: "Keep-Alive",
|
|
"Accept-Encoding": "gzip",
|
|
"User-Agent": "okhttp/4.9.2",
|
|
};
|
|
}
|
|
}
|