From c6120e5f684c809ed7201f9ac59866b5a779e6b9 Mon Sep 17 00:00:00 2001 From: minie4 Date: Fri, 2 Jun 2023 16:59:20 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Make=20the=20parser=20modular?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move some DSB related functions from parser/index to parser/dsbmobile - Make the dsb parser a fileProvider with the DSBClient class - Initialize the parser with a fileProvider and documentParser instance --- server/index.js | 6 +++-- server/parser/dsbmobile.js | 36 ++++++++++++++++++++++++++++ server/parser/index.js | 48 +++++++------------------------------- 3 files changed, 48 insertions(+), 42 deletions(-) diff --git a/server/index.js b/server/index.js index 4ea1817..2db67d8 100644 --- a/server/index.js +++ b/server/index.js @@ -11,6 +11,8 @@ import { } from "./api/index.js"; import auth from "./api/auth.js"; import { Parser } from "./parser/index.js"; +import { DSBClient } from "./parser/dsbmobile.js"; +import { parseSubstitutionPlan } from "./parser/untis.js"; // Check DSB Mobile credentials are supplied if (!process.env.DSB_USER || !process.env.DSB_PASSWORD) { @@ -28,8 +30,8 @@ app.use(express.urlencoded({ extended: true })); // Initialize the Parser and set it to update the // substitution plan at the specified update interval new Parser( - process.env.DSB_USER, - process.env.DSB_PASSWORD, + new DSBClient(process.env.DSB_USER, process.env.DSB_PASSWORD), + parseSubstitutionPlan, process.env.UPDATE_INTERVAL || 1 * 60 * 1000 // Default to 1 minute ); diff --git a/server/parser/dsbmobile.js b/server/parser/dsbmobile.js index 8a01354..e48cd02 100644 --- a/server/parser/dsbmobile.js +++ b/server/parser/dsbmobile.js @@ -1,4 +1,6 @@ import axios from "axios"; +import { log } from "../logs.js"; + const baseUrl = "https://mobileapi.dsbcontrol.de"; export async function getAuthtoken(username, password) { @@ -32,3 +34,37 @@ export async function getTimetables(authtoken) { return urls; } + +// List of files that include timetable data +const dsbFiles = ["Schüler_Monitor - subst_001", "Schüler Morgen - subst_001"]; + +export class DSBClient { + constructor(dsbUser, dsbPassword) { + this.dsbUser = dsbUser; + this.dsbPassword = dsbPassword; + } + async getFiles() { + try { + // Get authtoken + const token = await getAuthtoken(this.dsbUser, this.dsbPassword); + // Fetch available files + const response = await getTimetables(token); + // Filter files that should be parsed + const timetables = response.filter((e) => dsbFiles.includes(e.title)); + // Fetch the contents + const files = []; + for (let timetable of timetables) { + const result = await axios.request({ + method: "GET", + url: timetable.url, + responseEncoding: "binary", + }); + files.push(result.data); + } + + return files; + } catch (error) { + log("Parser / DSB Mobile", "Error getting data: " + error); + } + } +} diff --git a/server/parser/index.js b/server/parser/index.js index 1d37f32..1535fd6 100644 --- a/server/parser/index.js +++ b/server/parser/index.js @@ -1,18 +1,12 @@ import Prisma from "@prisma/client"; -import axios from "axios"; import { log, getLogPath } from "../logs.js"; -import { getAuthtoken, getTimetables } from "./dsbmobile.js"; -import { parseSubstitutionPlan } from "./untis.js"; -const dsbFiles = ["Schüler_Monitor - subst_001", "Schüler Morgen - subst_001"]; const prisma = new Prisma.PrismaClient(); export class Parser { - dsbUser; - dsbPassword; - constructor(dsbUser, dsbPassword, interval) { - this.dsbUser = dsbUser; - this.dsbPassword = dsbPassword; + constructor(fileProvider, documentParser, interval) { + this.fileProvider = fileProvider; + this.documentParser = documentParser; // Schedule plan updates setInterval(() => this.updatePlan(), interval); @@ -22,15 +16,13 @@ export class Parser { async updatePlan() { const startedAt = new Date(); try { - const data = await this.fetchDSB(); - if (!data) throw "DSB request failed!"; - + // Request substitution plan files using the fileProvider + const files = await this.fileProvider.getFiles(); const plans = []; - for (const entry of data) { - // Download the substitution plan - const file = await this.fetchFile(entry.url); + // Parse them using the provided parser + for (const file of files) { // Parse the substitution plan - const parsed = parseSubstitutionPlan(file); + const parsed = this.documentParser(file); plans.push(parsed); } // Create a new parse event @@ -61,30 +53,6 @@ export class Parser { log("Parser / Main", "Parse event failed: " + error); } } - async fetchDSB() { - try { - const token = await getAuthtoken(this.dsbUser, this.dsbPassword); - // Fetch available files - const response = await getTimetables(token); - // Filter files that should be parsed - const timetables = response.filter((e) => dsbFiles.includes(e.title)); - return timetables; - } catch (error) { - log("Parser / DSB Mobile", "Error getting data: " + error); - } - return false; - } - async fetchFile(url) { - const result = await axios.request({ - method: "GET", - url: url, - responseEncoding: "binary", - }); - return result.data; - } - async parsePlan(html) { - return parseSubstitutionPlan(html); - } async insertSubstitutions(parsedData, parseEvent) { const { date, changes } = parsedData; const classList = await prisma.class.findMany();