From 16a9bba6dd46c67965c4f361b7505d1aa2fad32f Mon Sep 17 00:00:00 2001 From: Mylloon Date: Mon, 18 Sep 2023 19:50:30 +0200 Subject: [PATCH] find the right timetable for the current semester/year combo --- src/main.rs | 47 +++++++++---------- src/timetable.rs | 114 +++++++++++++++++------------------------------ src/utils.rs | 11 +---- 3 files changed, 64 insertions(+), 108 deletions(-) diff --git a/src/main.rs b/src/main.rs index 189eb78..3828c65 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,14 +9,18 @@ mod utils; #[derive(Parser)] #[clap(version, about, long_about = None)] struct Args { - /// The class you want to get the timetable, i.e.: L2-A + /// The class you want to get the timetable, i.e.: M1-LP #[clap(value_parser)] class: String, - /// The semester you want (useful only in 3rd year, 1-2 use letter in class) + /// The semester you want (1 or 2) #[clap(short, long, value_parser, value_name = "SEMESTER NUMBER")] semester: Option, + /// The year, default to the current year + #[clap(short, long, value_parser, value_name = "YEAR")] + year: Option, + /// Export to iCalendar format (.ics) #[clap(short, long, value_name = "FILE NAME")] export: Option, @@ -30,38 +34,31 @@ struct Args { async fn main() { let args = Args::parse(); - let matches = Regex::new(r"[Ll](?P\d)[-–•·]?(?P.)?") - .unwrap() - .captures(&args.class) - .unwrap(); + let matches = + Regex::new(r"(?i)M(?P[1,2])[-–•·]?(?P(LP|IMPAIRS|DATA|GENIAL|MPRI))?") + .unwrap() + .captures(&args.class) + .unwrap(); - let year = matches - .name("year") + let level = matches + .name("level") .unwrap() .as_str() .parse::() .unwrap(); - let letter = matches - .name("letter") - .map(|c| c.as_str().chars().next().expect("Error in letter")); + let pathway = matches.name("pathway").unwrap().as_str(); - // Show a separator only if we need one - let seperator = match letter { - Some(_) => "-", - None => "", - }; - - let user_agent = format!("cal8tor/{}", env!("CARGO_PKG_VERSION")); + let user_agent = format!("cal7tor/{}", env!("CARGO_PKG_VERSION")); println!( - "Récupération de l'emploi du temps des L{}{}{}...", - year, - seperator, - letter.unwrap_or_default().to_uppercase() + "Récupération de l'emploi du temps des M{}-{}...", + level, + pathway.to_uppercase() ); - let timetable = timetable::timetable(year, args.semester, letter, &user_agent).await; + let timetable = + timetable::timetable(level, args.semester, args.year, pathway, &user_agent).await; - println!("Récupération des informations par rapport à l'année..."); + /* println!("Récupération des informations par rapport à l'année..."); let info = info::info(&user_agent).await; if args.export.is_some() { @@ -77,5 +74,5 @@ async fn main() { println!("Affichage..."); timetable::display(timetable, args.cl); println!("Vous devrez peut-être mettre votre terminal en plein écran si ce n'est pas déjà le cas."); - } + } */ } diff --git a/src/timetable.rs b/src/timetable.rs index 05bc6a7..9a8944d 100644 --- a/src/timetable.rs +++ b/src/timetable.rs @@ -12,19 +12,24 @@ pub mod models; /// Fetch the timetable for a class pub async fn timetable( - year: i8, + level: i8, semester_opt: Option, - letter: Option, + year_opt: Option, + pathway: &str, user_agent: &str, ) -> (Vec, (usize, Vec)) { - let semester = get_semester(semester_opt, letter); + let semester = get_semester(semester_opt); - let document = get_webpage(year, semester, letter, user_agent) + let year = get_year(year_opt, semester); + + let document = get_webpage(level, semester, &year, user_agent) .await .expect("Can't reach timetable website."); + (vec![], (0, vec![])) + // Selectors - let sel_table = Selector::parse("table").unwrap(); + /* let sel_table = Selector::parse("table").unwrap(); let sel_tr = Selector::parse("tr").unwrap(); let sel_tbody = Selector::parse("tbody").unwrap(); let sel_th = Selector::parse("th").unwrap(); @@ -116,59 +121,17 @@ pub async fn timetable( panic!("Error when building the timetable."); } - (schedules, (semester as usize, timetable)) + (schedules, (semester as usize, timetable)) */ } /// Get timetable webpage async fn get_webpage( - year: i8, + level: i8, semester: i8, - letter: Option, + year: &str, user_agent: &str, ) -> Result> { - let url = { - let panic_semester_message = "Unknown semester."; - let panic_letter_message = "Unknown letter."; - - let base_url = "https://informatique.up8.edu/licence-iv/edt"; - let allow_letters_1 = match semester { - 1 => ['a', 'b', 'c'], - 2 => ['x', 'y', 'z'], - _ => panic!("{}", panic_semester_message), - }; - let allow_letters_2_3 = match semester { - 1 => ['a', 'b'], - 2 => ['x', 'y'], - _ => panic!("{}", panic_semester_message), - }; - match year { - 1 => { - let c = letter.expect(panic_letter_message).to_ascii_lowercase(); - if allow_letters_1.contains(&c) { - format!("{}/l1-{}.html", base_url, c) - } else { - panic!("{}", panic_letter_message) - } - } - 2 => { - let c = letter.expect(panic_letter_message).to_ascii_lowercase(); - if allow_letters_2_3.contains(&c) { - format!("{}/l2-{}.html", base_url, c) - } else { - panic!("{}", panic_letter_message) - } - } - 3 => { - let c = letter.expect(panic_letter_message).to_ascii_lowercase(); - if allow_letters_2_3.contains(&c) { - format!("{}/l3-{}.html", base_url, c) - } else { - panic!("{}", panic_letter_message) - } - } - _ => panic!("Unknown year."), - } - }; + let url = format!("https://silice.informatique.univ-paris-diderot.fr/ufr/U{}/EDT/visualiserEmploiDuTemps.php?quoi=M{},{}", year, level, semester); // Use custom User-Agent let client = reqwest::Client::builder().user_agent(user_agent).build()?; @@ -314,34 +277,37 @@ pub fn build(timetable: T, dates: D) -> Vec { semester } -/// Get the current semester depending on the letter or the current date -fn get_semester(semester: Option, letter: Option) -> i8 { +/// Get the current semester depending on the current date +fn get_semester(semester: Option) -> i8 { match semester { // Force the asked semester Some(n) => n, // Find the potential semester - None => match letter { - // Based on letter (kinda accurate) - Some(c) => { - if c.to_ascii_uppercase() as i8 > 77 { - // If letter is N or after - 2 - } else { - // If letter is before N - 1 - } + None => { + if Utc::now().month() > 6 { + // From july to december + 1 + } else { + // from january to june + 2 } - // Based on the time (kinda less accurate) - None => { - if Utc::now().month() > 6 { - // From july to december - 1 - } else { - // from january to june - 2 - } - } - }, + } + } +} + +/// Get the current year depending on the current date +fn get_year(year: Option, semester: i8) -> String { + let wanted_year = match year { + // Force the asked semester + Some(n) => n, + // Find the potential semester + None => Utc::now().year(), + }; + + if semester == 1 { + format!("{}-{}", wanted_year, wanted_year + 1) + } else { + format!("{}-{}", wanted_year - 1, wanted_year) } } diff --git a/src/utils.rs b/src/utils.rs index c03101d..f7e3114 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -2,20 +2,13 @@ pub mod models; /// Panic if an error happened pub fn check_errors(html: &String, loc: &str) { + let no_timetable = "Aucun créneau horaire affecté"; match html { - t if t.contains(&err_code(429)) => panic!( - "URL: {} • HTTP 429: Slow down - Rate limited (too many access attempts detected)", - loc - ), + t if t.contains(no_timetable) => panic!("URL: {} • {}", loc, no_timetable), _ => (), } } -/// Create String error code -fn err_code(code: i32) -> String { - format!("HTTP Code : {}", code) -} - /// Print a line for the table pub fn line_table( cell_length_hours: usize,