Skip to content

Commit

Permalink
Merge pull request #466 from raphckrman/feature/canteen-alise
Browse files Browse the repository at this point in the history
Implémentation de Alise
  • Loading branch information
ecnivtwelve authored Dec 17, 2024
2 parents f33aa00 + 5a66a93 commit b6ab7e2
Show file tree
Hide file tree
Showing 28 changed files with 701 additions and 158 deletions.
Binary file added assets/images/service_alise.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
489 changes: 409 additions & 80 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@react-navigation/native": "^6.1.17",
"@react-navigation/native-stack": "^6.9.26",
"@react-navigation/stack": "^6.4.0",
"alise-api": "^0.1.2",
"axios": "^1.7.7",
"buffer": "^6.0.3",
"cal-parser": "^1.0.2",
Expand Down
4 changes: 3 additions & 1 deletion src/providers/AlertProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ const AlertProvider = ({ children }: AlertProviderProps) => {
<Pressable
key={title}
onPress={() => {
onPress();
if (onPress) {
onPress();
}
hideAlert();
}}
style={({ pressed }) => [
Expand Down
1 change: 1 addition & 0 deletions src/router/helpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ export type RouteParameters = {
ExternalTurboselfLogin: undefined;
ExternalArdLogin: undefined;
ExternalIzlyLogin: undefined;
ExternalAliseLogin: undefined;
IzlyActivation: { username: string; password: string };
PriceError: { account: Client; accountId: string };
QrcodeScanner: { accountID: string };
Expand Down
4 changes: 4 additions & 0 deletions src/router/screens/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import PriceBeforeScan from "@/views/settings/ExternalAccount/PriceBeforeScan";
import SettingsFlagsInfos from "@/views/settings/SettingsFlagsInfos";
import ExternalIzlyLogin from "@/views/settings/ExternalAccount/Izly";
import IzlyActivation from "@/views/settings/ExternalAccount/IzlyActivation";
import ExternalAliseLogin from "@/views/settings/ExternalAccount/Alise";

const settingsScreens = [
createScreen("Settings", Settings, {
Expand Down Expand Up @@ -101,6 +102,9 @@ const settingsScreens = [
createScreen("ExternalIzlyLogin", ExternalIzlyLogin, {
headerTitle: "Connexion à Izly",
}),
createScreen("ExternalAliseLogin", ExternalAliseLogin, {
headerTitle: "Connexion à Alise",
}),

createScreen("IzlyActivation", IzlyActivation, {
headerTitle: "Configuration de Izly",
Expand Down
14 changes: 14 additions & 0 deletions src/services/alise/balance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { AliseAccount } from "@/stores/account/types";
import type { Balance } from "../shared/Balance";

export const getBalance = async (account: AliseAccount, force = false): Promise<Array<Balance>> => {
const balance = force ? (await account.authentication.session.getInformations()).balance : account.authentication.session.account?.balance ?? 0;
const mealPrice = account.authentication.mealPrice;

return [{
amount: balance,
currency: "€",
remaining: Math.floor(balance / (mealPrice ?? 0)),
label: "Self"
}];
};
26 changes: 26 additions & 0 deletions src/services/alise/bookings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { AliseAccount } from "@/stores/account/types";
import type { BookingDay, BookingTerminal } from "../shared/Booking";

export const getBookings = async (account: AliseAccount, force = false): Promise<BookingTerminal[]> => {
const bookings = force ? await account.authentication.session.getBookings() : await account.authentication.bookings;
return [{
id: "",
terminalLabel: "Self",
days: bookings.map((day) => ({
id: (day.identifier ?? ""),
canBook: day.canBook,
date: day.date,
booked: day.booked
})),
account: account
}];
};

export const bookDay = async (account: AliseAccount, id: string, date: Date, booked: boolean): Promise<BookingDay> => {
const bookedDay = await account.authentication.session.bookDay(id, 1, !booked);
return {
id: bookedDay.identifier ?? "",
canBook: bookedDay.canBook,
booked: bookedDay.booked,
};
};
12 changes: 12 additions & 0 deletions src/services/alise/history.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { AliseAccount } from "@/stores/account/types";
import type { ReservationHistory } from "../shared/ReservationHistory";

export const getHistory = async (account: AliseAccount): Promise<ReservationHistory[]> => {
const history = await account.authentication.session.getFinancialHistory();
return (history ?? []).map((item) => ({
timestamp: item.date.getTime(),
amount: item.amount,
currency: "€",
label: item.label,
}));
};
16 changes: 16 additions & 0 deletions src/services/alise/reload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { AliseAccount } from "@/stores/account/types";
import { authenticateWithCredentials } from "alise-api";

export const reload = async (account: AliseAccount): Promise<AliseAccount["authentication"]> => {
const auth = { ...account.authentication };
const session = await authenticateWithCredentials(auth.username, auth.password, auth.schoolID);
const bookings = await session.getBookings();
return {
session,
schoolID: auth.schoolID,
username: auth.username,
password: auth.password,
mealPrice: auth.mealPrice,
bookings: bookings
};
};
6 changes: 5 additions & 1 deletion src/services/balance.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {AccountService, type ExternalAccount} from "@/stores/account/types";
import type {Balance} from "./shared/Balance";

export const balanceFromExternal = async (account: ExternalAccount): Promise<Balance[]> => {
export const balanceFromExternal = async (account: ExternalAccount, force = false): Promise<Balance[]> => {
switch (account.service) {
case AccountService.Turboself: {
const { getBalance } = await import("./turboself/balance");
Expand All @@ -15,6 +15,10 @@ export const balanceFromExternal = async (account: ExternalAccount): Promise<Bal
const { balance } = await import("./izly/balance");
return balance(account);
}
case AccountService.Alise: {
const { getBalance } = await import("./alise/balance");
return getBalance(account, force);
}
default: {
return [];
}
Expand Down
12 changes: 11 additions & 1 deletion src/services/booking.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AccountService, type ExternalAccount } from "@/stores/account/types";
import type { BookingDay, BookingTerminal } from "./shared/Booking";

export const getBookingsAvailableFromExternal = async (account: ExternalAccount, weekNumber?: number): Promise<BookingTerminal[]> => {
export const getBookingsAvailableFromExternal = async (account: ExternalAccount, weekNumber?: number, force = false): Promise<BookingTerminal[]> => {
switch (account.service) {
case AccountService.Turboself: {
const { getBookingWeek } = await import("./turboself/booking");
Expand All @@ -14,6 +14,11 @@ export const getBookingsAvailableFromExternal = async (account: ExternalAccount,
// TODO: Implement ARD
return [];
}
case AccountService.Alise: {
const { getBookings } = await import("./alise/bookings");
const bookings = await getBookings(account, force);
return bookings;
}
default: {
return [];
}
Expand All @@ -27,6 +32,11 @@ export const bookDayFromExternal = async (account: ExternalAccount, id: string,
const bookedDay = await bookDay(account, id, date, booked);
return bookedDay;
}
case AccountService.Alise: {
const { bookDay } = await import("./alise/bookings");
const bookedDay = await bookDay(account, id, date, booked);
return bookedDay;
}
case AccountService.ARD: {
return undefined;
}
Expand Down
2 changes: 1 addition & 1 deletion src/services/ecoledirecte/attendance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {Absence} from "@/services/shared/Absence";
import {Delay} from "@/services/shared/Delay";

const decodeDelay = (item: AttendanceItem): Delay => {
const timeInterval = dateStringAsTimeInterval(item.displayDate);
const timeInterval = dateStringAsTimeInterval(item.displayDate);
const duration = (timeInterval?.end && timeInterval.start) ? getDuration(timeInterval).getTime() / (60 * 1000): 0;
return {
id: item.id.toString(),
Expand Down
4 changes: 2 additions & 2 deletions src/services/ecoledirecte/chats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ export const getChats = async (account: EcoleDirecteAccount): Promise<Chat[]> =>
};

const cleanMessage = (message: string) => {
return message.replace(/>\s+/g, '>').replace(/&nbsp;/g, ' ');
}
return message.replace(/>\s+/g, ">").replace(/&nbsp;/g, " ");
};

export const getChatMessages = async (account: EcoleDirecteAccount, chat: Chat): Promise<ChatMessage> => {
if (!account.instance)
Expand Down
4 changes: 2 additions & 2 deletions src/services/ecoledirecte/homework.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { AttachmentType } from "../shared/Attachment";
import { formatDate } from "@/services/ecoledirecte/format-date";

const cleanContent = (message: string) => {
return message.replace(/>\s+/g, '>').replace(/&nbsp;/g, ' ');
}
return message.replace(/>\s+/g, ">").replace(/&nbsp;/g, " ");
};

export const getHomeworkForWeek = async (
account: EcoleDirecteAccount,
Expand Down
88 changes: 44 additions & 44 deletions src/services/ecoledirecte/time-interval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,74 +8,74 @@ const months = ["janvier", "février", "mars", "avril", "mai", "juin", "juillet"
/**
* @param str "A string containing a date formatted as "mercredi 21 février 2024 de 08:10", will return the date for the specified day and hour"
*/
export function dateAsISO860(str: string): string {
export function dateAsISO860 (str: string): string {
const parts = str.split(" ");
const timeIndex = parts.findIndex(part => part.includes(":"));
const hour = parts[timeIndex].split(":");
const monthIndex = parts.findIndex(part => months.includes(part));

return (new Date(
Number(parts[monthIndex + 1]),
months.indexOf(parts[monthIndex]),
Number(parts[monthIndex - 1]),
Number(hour[0]),
Number(hour[1])
Number(parts[monthIndex + 1]),
months.indexOf(parts[monthIndex]),
Number(parts[monthIndex - 1]),
Number(hour[0]),
Number(hour[1])
)).toISOString();
}

export function dateStringAsTimeInterval(
export function dateStringAsTimeInterval (
str: string,
): Timeinterval | undefined {
if (str.includes("du")) {
/**
/**
* @example
* str is equal to "du mercredi 21 février 2024 au jeudi 22 février 2024"
* or "du mercredi 27 novembre 2024 à 08:10 au vendredi 06 décembre 2024 à 08:10"
*/
const [startPart, endPart] = str.split("au").map(part => part.trim());
let start = startPart.replace("du", "").trim();
let end = endPart.trim();
const [startPart, endPart] = str.split("au").map(part => part.trim());
let start = startPart.replace("du", "").trim();
let end = endPart.trim();

if (!start.includes(":")) {
start += " de 00:00";
} else {
start = start.replace(" à ", " de ");
}
if (!start.includes(":")) {
start += " de 00:00";
} else {
start = start.replace(" à ", " de ");
}

if (!end.includes(":")) {
end += " de 23:59";
} else {
end = end.replace(" à ", " de ");
}
if (!end.includes(":")) {
end += " de 23:59";
} else {
end = end.replace(" à ", " de ");
}

return {
start: dateAsISO860(start),
end: dateAsISO860(end)
} as Timeinterval;
return {
start: dateAsISO860(start),
end: dateAsISO860(end)
} as Timeinterval;
}

if (str.includes("le")) {
/**
/**
* @example
* str is equal to "le mercredi 21 février 2024 de 08:10 à 16:10"
* or "le jeudi 22 février 2024"
*/
const parts = str.split("à");
let startDate: string;
let endDate: string;
const parts = str.split("à");
let startDate: string;
let endDate: string;

// It's a full day ("le mercredi 21 février 2024")
if (!str.includes(":")) {
startDate = `${parts[0].replace("le", "").trim()} de 00:00`;
endDate = `${parts[0].split("de")[0].replace("le", "").trim()} de 23:59`;
} else {
startDate = parts[0].replace("le", "").trim();
endDate = `${parts[0].split("de")[0].replace("le", "").trim()} de ${parts[1].trim()}`;
}
// It's a full day ("le mercredi 21 février 2024")
if (!str.includes(":")) {
startDate = `${parts[0].replace("le", "").trim()} de 00:00`;
endDate = `${parts[0].split("de")[0].replace("le", "").trim()} de 23:59`;
} else {
startDate = parts[0].replace("le", "").trim();
endDate = `${parts[0].split("de")[0].replace("le", "").trim()} de ${parts[1].trim()}`;
}

const start = dateAsISO860(startDate);
const end = dateAsISO860(endDate);
return { start: start, end: end } as Timeinterval;
const start = dateAsISO860(startDate);
const end = dateAsISO860(endDate);
return { start: start, end: end } as Timeinterval;
}
return undefined;
}
Expand All @@ -100,6 +100,6 @@ export const getDurationInHours = (interval: Timeinterval): string => {
const diff = new Date(interval.end).getTime() - new Date(interval.start).getTime();
const hours = Math.floor(diff / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
return `${hours}h${minutes.toString().padStart(2, '0')}`;

return `${hours}h${minutes.toString().padStart(2, "0")}`;
};
5 changes: 5 additions & 0 deletions src/services/reload-account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ export async function reload <T extends Account> (account: T): Promise<Reconnect
// keep instance the same
return { instance: undefined, authentication: auth };
}
case AccountService.Alise: {
const { reload } = await import("./alise/reload");
const auth = await reload(account);
return { instance: undefined, authentication: auth };
}
case AccountService.ARD: {
const { reload } = await import("./ard/reload");
const instance = await reload(account);
Expand Down
4 changes: 4 additions & 0 deletions src/services/reservation-history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export const reservationHistoryFromExternal = async (account: ExternalAccount):
const { history: getHistory } = await import("./izly/history");
return getHistory(account);
}
case AccountService.Alise: {
const { getHistory } = await import("./alise/history");
return getHistory(account);
}
default: {
return [];
}
Expand Down
10 changes: 3 additions & 7 deletions src/services/shared/Booking.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import { ARDAccount, TurboselfAccount } from "@/stores/account/types";
import { AliseAccount, ARDAccount, TurboselfAccount } from "@/stores/account/types";

export interface BookingTerminal {
id: string;
week: number;
from: Date;
to: Date;
terminalLabel: string;
days: BookingDay[];
account: TurboselfAccount | ARDAccount;
account: TurboselfAccount | ARDAccount | AliseAccount;
}

export interface BookingDay {
id: string;
canBook: boolean;
date: Date;
message: string;
date?: Date;
booked: boolean;
}
Loading

0 comments on commit b6ab7e2

Please sign in to comment.