Skip to content

Commit

Permalink
feat: implement instance information getter
Browse files Browse the repository at this point in the history
  • Loading branch information
Vexcited committed Jan 18, 2024
1 parent 58d4178 commit 2ea9cf8
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 3 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ It returns a boolean that is `true` when the server is a demo.
- [x] parser: able to get/build attachment's URL
- [x] Find Pronote instances with longitude and latitude
- [x] `findPronoteInstances(fetcher, { longitude, latitude })`
- [x] Get information about an instance from its URL
- [x] `getPronoteInstanceInformation(fetcher, { pronoteURL })`
- [x] Periods
- [x] client: `.periods` (property)
- [x] parser: `Period`
Expand Down
22 changes: 22 additions & 0 deletions examples/instance-information.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { getPronoteInstanceInformation, defaultPawnoteFetcher } from "../src";

(async () => {
const instance = await getPronoteInstanceInformation(defaultPawnoteFetcher, {
pronoteURL: "https://demo.index-education.net/pronote"
});

console.log("Root URL:", instance.pronoteRootURL);
console.log("School Name:", instance.schoolName);
console.log("Server Version:", instance.version);

console.group("Available account types:", instance.accounts.length);
instance.accounts.forEach(account => {
console.log("->", account.name, `(${account.id})`);
})
console.groupEnd();

if (instance.entURL) {
console.log("ENT is activated, base URL is", instance.entURL);
console.log("-> ENT token:", instance.entToken!);
}
})();
2 changes: 1 addition & 1 deletion src/api/geolocation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const callApiGeolocation = makeApiHandler<ApiGeolocation>(async (fetcher,
body: searchParamsBody.toString()
});

let data = await response.json() as PronoteApiGeolocation["response"];
let data = await response.json<PronoteApiGeolocation["response"]>();
data = Array.isArray(data) ? data : [];

// Restructure the results to be more readable.
Expand Down
2 changes: 2 additions & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { callApiUserHomework } from "./user/homework";
export { callApiUserHomeworkStatus } from "./user/homeworkStatus";
export { callApiUserTimetable } from "./user/timetable";
export { callApiGeolocation } from "./geolocation";
export { callApiInstance } from "./instance";

export type { ApiLoginInformations, PronoteApiLoginInformations } from "./login/informations/types";
export type { ApiLoginIdentify, PronoteApiLoginIdentify } from "./login/identify/types";
Expand All @@ -15,3 +16,4 @@ export type { ApiUserHomework, PronoteApiUserHomework } from "./user/homework/ty
export type { ApiUserHomeworkStatus, PronoteApiUserHomeworkStatus } from "./user/homeworkStatus/types";
export type { ApiUserTimetable, PronoteApiUserTimetable } from "./user/timetable/types";
export type { ApiGeolocation, PronoteApiGeolocation } from "./geolocation/types";
export type { ApiInstance, PronoteApiInstance } from "./instance/types";
50 changes: 50 additions & 0 deletions src/api/instance/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { makeApiHandler } from "~/utils/api";
import type { PronoteApiInstance, ApiInstance } from "./types";
import { cleanPronoteUrl } from "~/pronote/url";
import { PRONOTE_ACCOUNT_TYPES, PronoteApiAccountType } from "~/constants/accounts";
import { PRONOTE_INSTANCE_MOBILE_INFOS_PATH } from "~/constants/urls";

/**
* Filter function to prevent TS issues.
* Allows to check that every item is defined and make them typed to `PronoteApiAccountType`.
*/
const isPronoteApiAccountType = (item: PronoteApiAccountType | undefined): item is PronoteApiAccountType => {
return Boolean(item);
};

/**
* Takes an instance URL and return informations about it such as...
* - available account types ;
* - instance name ;
* - base URL and potential ENT URL
*/
export const callApiInstance = makeApiHandler<ApiInstance>(async (fetcher, input) => {
const pronoteURL = cleanPronoteUrl(input.pronoteURL);
const informationURL = `${pronoteURL}/${PRONOTE_INSTANCE_MOBILE_INFOS_PATH}`;

const response = await fetcher(informationURL, {
method: "GET"
});

// Build the local date to get the timezone offset, right after.
// const local_date = new Date(new Date().toLocaleString("fr-FR", { timeZone: req.body.timezone }));

const data = await response.json<PronoteApiInstance["response"]>();

// Calculate the timezone offset between the server and the client.
// const timezone_offset = local_date.getTime() - new Date(data.date).getTime();

// Filter the accounts to only keep the ones that are supported.
const accounts = data.espaces.map((account) => PRONOTE_ACCOUNT_TYPES.find(
(account_type) => account_type.path === account.URL
)).filter(isPronoteApiAccountType);

return {
accounts,
pronoteRootURL: pronoteURL,
version: data.version[0],
schoolName: data.nomEtab,
entURL: data.CAS.actif ? data.CAS.casURL : undefined,
entToken: data.CAS.actif ? data.CAS.jetonCAS : undefined
};
});
36 changes: 36 additions & 0 deletions src/api/instance/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { PronoteApiAccountId } from "~/constants/accounts";

export interface PronoteApiInstance {
request: Record<string, never>

response: {
version: number[]
date: string
CAS: { actif: false } | { actif: true, casURL: string, jetonCAS: string }
espaces: Array<{ nom: string, URL: string }>
nomEtab: string
}
}

export interface ApiInstance {
input: {
pronoteURL: string
}

output: {
version: number;
schoolName: string;

accounts: Array<{
name: string
id: PronoteApiAccountId
}>

pronoteRootURL: string

/** URL of the ENT we have to handle. */
entURL?: string
/** Used to generate new temporary passwords for Pronote after ENT login. */
entToken?: string
}
}
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ export { PronoteApiAccountId } from "~/constants/accounts";
export { authenticatePronoteCredentials, authenticateToken, authenticatePronoteQRCode } from "~/authenticate";
export { PronoteApiGradeType } from "./pronote/grades";

// Geolocation.
export { callApiGeolocation as findPronoteInstances } from "~/api";
export { callApiGeolocation as findPronoteInstances, callApiInstance as getPronoteInstanceInformation } from "~/api";

import type { ApiGeolocation } from "~/api";

/**
Expand Down

0 comments on commit 2ea9cf8

Please sign in to comment.