mirror of
https://github.com/dd060606/WebAurion-API.git
synced 2026-01-18 16:47:26 +01:00
work on schedule API
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
import { getJSONSchedule, getViewState } from "../utils/AurionUtils";
|
||||
import {
|
||||
getJSFFormParams,
|
||||
getViewState,
|
||||
scheduleResponseToEvents,
|
||||
} from "../utils/AurionUtils";
|
||||
import Session from "./Session";
|
||||
|
||||
class ScheduleApi {
|
||||
@@ -7,75 +11,66 @@ class ScheduleApi {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public fetchSchedule(): Promise<string> {
|
||||
return new Promise<string>(async (resolve, reject) => {
|
||||
// Récupération de l'emploi du temps en fonction de la date de début et de fin (timestamps en millisecondes)
|
||||
public fetchSchedule(
|
||||
startDate?: string,
|
||||
endDate?: string,
|
||||
): Promise<ScheduleEvent[]> {
|
||||
return new Promise<ScheduleEvent[]>(async (resolve, reject) => {
|
||||
try {
|
||||
const schedulePage = await this.session.sendGET<string>(
|
||||
"/faces/Planning.xhtml",
|
||||
);
|
||||
let viewState = getViewState(schedulePage);
|
||||
if (viewState) {
|
||||
const params = new URLSearchParams();
|
||||
// On ajoute les paramètres nécessaires pour effectuer une requête POST
|
||||
params.append("javax.faces.partial.ajax", "true");
|
||||
params.append("javax.faces.source", "form:j_idt46");
|
||||
params.append(
|
||||
"javax.faces.partial.execute",
|
||||
"form:j_idt46",
|
||||
// Ici 291906 correspond au menu 'Scolarité' dans la sidebar
|
||||
// Requête utile pour intialiser le ViewState (obligatoire pour effectuer une requête)
|
||||
await this.session.sendSidebarRequest("291906", viewState);
|
||||
|
||||
// Ici 1_4 correspond au sous-menu 'Emploi du temps' dans la sidebar
|
||||
// On récupère le ViewState pour effectuer la prochaine requête
|
||||
viewState = await this.session.sendSidebarSubmenuRequest(
|
||||
"1_4",
|
||||
viewState,
|
||||
);
|
||||
params.append("javax.faces.partial.render", "form:sidebar");
|
||||
params.append("form:j_idt46", "form:j_idt46");
|
||||
params.append(
|
||||
"webscolaapp.Sidebar.ID_SUBMENU",
|
||||
"submenu_291906",
|
||||
|
||||
// On envoie enfin la requête pour obtenir l'emploi du temps
|
||||
const params = getJSFFormParams(
|
||||
"j_idt118",
|
||||
"j_idt118",
|
||||
viewState,
|
||||
);
|
||||
params.append("form", "form");
|
||||
params.append("javax.faces.ViewState", viewState);
|
||||
if (startDate && endDate) {
|
||||
params.append("form:j_idt118_start", startDate);
|
||||
params.append("form:j_idt118_end", endDate);
|
||||
} else {
|
||||
// On récupère le timestamp du lundi de la semaine en cours
|
||||
const currentDate = new Date();
|
||||
const currentDay = currentDate.getDay();
|
||||
const daysUntilMonday =
|
||||
(currentDay === 0 ? 1 : 8) - currentDay;
|
||||
currentDate.setDate(
|
||||
currentDate.getDate() + daysUntilMonday,
|
||||
);
|
||||
currentDate.setHours(0, 0, 0, 0);
|
||||
const startTimestamp = currentDate.getTime();
|
||||
const endTimestamp =
|
||||
startTimestamp + 6 * 24 * 60 * 60 * 1000;
|
||||
params.append(
|
||||
"form:j_idt118_start",
|
||||
startTimestamp.toString(),
|
||||
);
|
||||
params.append(
|
||||
"form:j_idt118_end",
|
||||
endTimestamp.toString(),
|
||||
);
|
||||
}
|
||||
|
||||
const response = await this.session.sendPOST<string>(
|
||||
"faces/Planning.xhtml",
|
||||
params,
|
||||
);
|
||||
|
||||
const params2 = new URLSearchParams();
|
||||
// On ajoute les paramètres nécessaires pour effectuer une requête POST
|
||||
params2.append("form", "form");
|
||||
params2.append("javax.faces.ViewState", viewState);
|
||||
params2.append("form:sidebar", "form:sidebar");
|
||||
params2.append("form:sidebar_menuid", "1_4");
|
||||
const response2 = await this.session.sendPOST<string>(
|
||||
"faces/Planning.xhtml",
|
||||
params2,
|
||||
);
|
||||
viewState = getViewState(response2);
|
||||
if (!viewState) {
|
||||
return reject(new Error("Viewstate not found"));
|
||||
}
|
||||
const params3 = new URLSearchParams();
|
||||
params3.append("javax.faces.partial.ajax", "true");
|
||||
params3.append("javax.faces.source", "form:j_idt118");
|
||||
params3.append(
|
||||
"javax.faces.partial.execute",
|
||||
"form:j_idt118",
|
||||
);
|
||||
params3.append(
|
||||
"javax.faces.partial.render",
|
||||
"form:j_idt118",
|
||||
);
|
||||
params3.append("form:j_idt118", "form:j_idt118");
|
||||
params3.append("form:j_idt118_start", "1731279600000");
|
||||
params3.append("form:j_idt118_end", "1731798000000");
|
||||
params3.append("form", "form");
|
||||
params3.append(
|
||||
"form:idInit",
|
||||
"webscolaapp.Planning_-6802915683822110557",
|
||||
);
|
||||
params3.append("javax.faces.ViewState", viewState);
|
||||
const response3 = await this.session.sendPOST<string>(
|
||||
"faces/Planning.xhtml",
|
||||
params3,
|
||||
);
|
||||
console.log(getJSONSchedule(response3));
|
||||
resolve(response2);
|
||||
resolve(scheduleResponseToEvents(response));
|
||||
} else {
|
||||
reject(new Error("Viewstate not found"));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import axios, { AxiosInstance } from "axios";
|
||||
import ScheduleApi from "./ScheduleApi";
|
||||
import { getJSFFormParams, getViewState } from "../utils/AurionUtils";
|
||||
|
||||
class Session {
|
||||
private client: AxiosInstance;
|
||||
@@ -19,6 +20,66 @@ class Session {
|
||||
return new ScheduleApi(this);
|
||||
}
|
||||
|
||||
// (1ère phase) Besoin de simuler le clic sur la sidebar pour obtenir le ViewState nécessaire aux fonctionnements des reqûetes
|
||||
public sendSidebarRequest(
|
||||
subMenuId: string,
|
||||
viewState: string,
|
||||
): Promise<string> {
|
||||
return new Promise<string>(async (resolve, reject) => {
|
||||
try {
|
||||
// 1 ère sidebar: formId = j_idt46, renderId = sidebar
|
||||
const params = getJSFFormParams(
|
||||
"j_idt46",
|
||||
"sidebar",
|
||||
viewState,
|
||||
);
|
||||
// On ajoute l'ID du sous-menu qui correspond à la rubrique chosie (Scolarité, mon compte, divers, ...)
|
||||
params.append(
|
||||
"webscolaapp.Sidebar.ID_SUBMENU",
|
||||
`submenu_${subMenuId}`,
|
||||
);
|
||||
// On envoie la requête POST
|
||||
const response = await this.sendPOST<string>(
|
||||
"faces/Planning.xhtml",
|
||||
params,
|
||||
);
|
||||
resolve(response);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// (2ème phase) Simulation du sous menu de la side bar pour obtenir le ViewState nécessaire aux fonctionnements des requêtes
|
||||
// Cette fonction retourne un second ViewState qui sera utilisé pour effectuer les prochaines requêtes POST
|
||||
public sendSidebarSubmenuRequest(
|
||||
subMenuId: string,
|
||||
viewState: string,
|
||||
): Promise<string> {
|
||||
return new Promise<string>(async (resolve, reject) => {
|
||||
try {
|
||||
const params = new URLSearchParams();
|
||||
// On ajoute les paramètres nécessaires pour effectuer une requête POST
|
||||
params.append("form", "form");
|
||||
params.append("javax.faces.ViewState", viewState);
|
||||
params.append("form:sidebar", "form:sidebar");
|
||||
params.append("form:sidebar_menuid", subMenuId);
|
||||
const response = await this.sendPOST<string>(
|
||||
"faces/Planning.xhtml",
|
||||
params,
|
||||
);
|
||||
const secondViewState = getViewState(response);
|
||||
if (secondViewState) {
|
||||
resolve(secondViewState);
|
||||
} else {
|
||||
reject(new Error("Viewstate not found"));
|
||||
}
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public sendGET<T>(url: string): Promise<T> {
|
||||
return this.client.get<T>(url).then((response) => response.data);
|
||||
}
|
||||
|
||||
@@ -22,3 +22,60 @@ export function getJSONSchedule(xml: string): object {
|
||||
const json = parser('update[id="form:j_idt118"]').text();
|
||||
return JSON.parse(json)["events"];
|
||||
}
|
||||
|
||||
export function scheduleResponseToEvents(response: string): ScheduleEvent[] {
|
||||
const json: any = getJSONSchedule(response);
|
||||
|
||||
return json.map((event: any) => {
|
||||
// On récupère les informations des cours
|
||||
const eventInfo = event.title.split(" - ");
|
||||
|
||||
let room = eventInfo[1].trim();
|
||||
// Pour les matières qui ne sont pas bien formatées...
|
||||
let subject = "";
|
||||
let title = "";
|
||||
if (eventInfo.length >= 9) {
|
||||
subject = eventInfo[eventInfo.length - 5].trim();
|
||||
title = eventInfo[eventInfo.length - 4].trim();
|
||||
} else {
|
||||
subject = eventInfo[eventInfo.length - 4].trim();
|
||||
title = eventInfo[eventInfo.length - 3].trim();
|
||||
}
|
||||
|
||||
let instructors = eventInfo[eventInfo.length - 2].trim();
|
||||
let learners = eventInfo[eventInfo.length - 1].trim();
|
||||
|
||||
return {
|
||||
id: event.id,
|
||||
title,
|
||||
subject,
|
||||
room,
|
||||
instructors,
|
||||
learners,
|
||||
start: event.start,
|
||||
end: event.end,
|
||||
allDay: event.allDay,
|
||||
editable: event.editable,
|
||||
className: event.className,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// Paramètres nécessaires pour effectuer une requête avec le backend Java Server Faces (JSF)
|
||||
// Form ID : ID du formulaire (Récupérable avec BurpSuite / Inspecteur de requêtes)
|
||||
// Render ID : ID de l'élément à mettre à jour (Récupérable avec BurpSuite / Inspecteur de requêtes)
|
||||
export function getJSFFormParams(
|
||||
formId: string,
|
||||
renderId: string,
|
||||
viewState: string,
|
||||
): URLSearchParams {
|
||||
const params = new URLSearchParams();
|
||||
params.append("javax.faces.partial.ajax", "true");
|
||||
params.append("javax.faces.source", `form:${formId}`);
|
||||
params.append("javax.faces.partial.execute", `form:${formId}`);
|
||||
params.append("javax.faces.partial.render", `form:${renderId}`);
|
||||
params.append(`form:${formId}`, `form:${formId}`);
|
||||
params.append("form", "form");
|
||||
params.append("javax.faces.ViewState", viewState);
|
||||
return params;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
type ScheduleEvent = {
|
||||
id: string;
|
||||
title: string;
|
||||
subject: string;
|
||||
room: string;
|
||||
instructors: string;
|
||||
learners: string;
|
||||
start: string;
|
||||
end: string;
|
||||
allDay: boolean;
|
||||
editable: boolean;
|
||||
className: string;
|
||||
};
|
||||
|
||||
@@ -10,6 +10,8 @@ describe("ScheduleApi", () => {
|
||||
}
|
||||
|
||||
const session = await login(username, password);
|
||||
await session.getScheduleApi().fetchSchedule();
|
||||
const schedule = await session.getScheduleApi().fetchSchedule();
|
||||
console.log(schedule);
|
||||
expect(schedule).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user