🚧 Started working on processing of substitutions
This commit is contained in:
149
server/parser/index.js
Normal file
149
server/parser/index.js
Normal file
@ -0,0 +1,149 @@
|
||||
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";
|
||||
import fs from "fs";
|
||||
|
||||
const prisma = new Prisma.PrismaClient();
|
||||
|
||||
const dsbFiles = ["Schüler_Monitor - subst_001", "Schüler Morgen - subst_001"];
|
||||
|
||||
export class Parser {
|
||||
dsbUser;
|
||||
dsbPassword;
|
||||
constructor(dsbUser, dsbPassword, interval) {
|
||||
this.dsbUser = dsbUser;
|
||||
this.dsbPassword = dsbPassword;
|
||||
|
||||
// setInterval(this.updatePlan, interval);
|
||||
// this.updatePlan();
|
||||
(async () => {
|
||||
const event = await prisma.parseEvent.findFirst({
|
||||
where: {
|
||||
succeeded: true,
|
||||
},
|
||||
});
|
||||
const plan = JSON.parse(fs.readFileSync("tmpplans.json"));
|
||||
this.insertSubstitutions(plan, event);
|
||||
})();
|
||||
}
|
||||
async updatePlan() {
|
||||
const startedAt = new Date();
|
||||
try {
|
||||
const data = await this.fetchDSB();
|
||||
if (!data) {
|
||||
throw "DSB request failed!";
|
||||
}
|
||||
const plans = [];
|
||||
for (const entry of data) {
|
||||
const data = await this.fetchFile(entry.url);
|
||||
const parsed = parseSubstitutionPlan(data);
|
||||
plans.push(parsed);
|
||||
}
|
||||
const parseEvent = await prisma.parseEvent.create({
|
||||
data: {
|
||||
logFile: getLogPath(),
|
||||
originalData: "",
|
||||
duration: new Date() - startedAt,
|
||||
succeeded: true,
|
||||
},
|
||||
});
|
||||
for (const plan of plans) {
|
||||
await this.insertSubstitutions(plans, parseEvent);
|
||||
fs.writeFileSync("tmpfile", JSON.stringify(plan));
|
||||
}
|
||||
} catch (error) {
|
||||
await prisma.parseEvent.create({
|
||||
data: {
|
||||
logFile: getLogPath(),
|
||||
originalData: error.toString(),
|
||||
duration: new Date() - startedAt,
|
||||
succeeded: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
async fetchDSB() {
|
||||
try {
|
||||
const token = await getAuthtoken(this.dsbUser, this.dsbPassword);
|
||||
const response = await getTimetables(token);
|
||||
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 { updatedAt, date, changes } = parsedData;
|
||||
const classList = await prisma.class.findMany();
|
||||
|
||||
const knownSubstitutions = await prisma.substitution.findMany({
|
||||
where: {
|
||||
date: new Date(new Date(date).setUTCHours(0, 0, 0, 0)),
|
||||
},
|
||||
});
|
||||
|
||||
for (const change of changes) {
|
||||
const classes = this.getSubstitutionClasses(classList, change.class);
|
||||
if (classes.length == 0) classes.push(change.class || "unknown");
|
||||
|
||||
const matchingSubstitution = knownSubstitutions.find((substitution) => {
|
||||
return substitution.date == new Date(date).setUTCHours(0, 0, 0, 0) &&
|
||||
substitution.type == (change.type == "Entfall")
|
||||
? "cancellation"
|
||||
: "change" &&
|
||||
substitution.lesson == change.lesson &&
|
||||
classes.every((el) => substitution.class.includes(el)) &&
|
||||
substitution.changedSubject == change.subject;
|
||||
});
|
||||
|
||||
if (!matchingSubstitution) {
|
||||
const newSubstitution = await prisma.substitution.create({
|
||||
data: {
|
||||
class: classes,
|
||||
date: new Date(date),
|
||||
type: change.type == "Entfall" ? "cancellation" : "change",
|
||||
lesson: parseInt(change.lesson),
|
||||
changedTeacher: change.changedTeacher,
|
||||
changedRoom: change.type == "Raum-Vtr." ? change.room : undefined,
|
||||
changedSubject: change.subject,
|
||||
notes: change.notes,
|
||||
removed: false,
|
||||
},
|
||||
});
|
||||
const substitutionChange = await prisma.substitutionChange.create({
|
||||
data: {
|
||||
substitutionId: newSubstitution.id,
|
||||
type: "addition",
|
||||
changes: {},
|
||||
parseEventId: parseEvent.id,
|
||||
},
|
||||
});
|
||||
log(
|
||||
"Insert / DB",
|
||||
`Created new substitution: S:${newSubstitution.id} C:${substitutionChange.id}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
getSubstitutionClasses(classList, classString) {
|
||||
const matchingClasses = classList.filter((element) => {
|
||||
const regex = new RegExp(element.regex);
|
||||
return (classString || "").toLowerCase().match(regex);
|
||||
});
|
||||
return matchingClasses.map((e) => e.name);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user