Skip to content
70 changes: 70 additions & 0 deletions aoc-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,76 @@ impl AocClient {
Ok(())
}

fn get_personal_stats_html(&self) -> AocResult<String> {
debug!("🦌 Fetching {} personal stats", self.year);

let url =
format!("https://adventofcode.com/{}/leaderboard/self", self.year);
let response = http_client(&self.session_cookie, "text/html")?
.get(url)
.send()?;

if response.status() == StatusCode::NOT_FOUND {
// A 402 reponse means the calendar for
// the requested year is not yet available
return Err(AocError::InvalidEventYear(self.year));
} else if response.status() == StatusCode::FOUND {
// A 302 reponse is a redirect and it likely
// means we're not logged in
warn!(
"🍪 It looks like you are not logged in, try logging in again"
);
return Err(AocError::AocResponseError);
}
Comment on lines 437 to 447
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this deserves a new error, say AocError::NotLoggedIn. When showing the calendar not being logged in isn't a problem as you can still show the calendar with no stars. But here it's different...


let contents = response.error_for_status()?.text()?;

let main = Regex::new(r"(?i)(?s)<main>(?P<main>.*)</main>")
.unwrap()
.captures(&contents)
.ok_or(AocError::AocResponseError)?
.name("main")
.unwrap()
.as_str()
.to_string();

Ok(main)
}

pub fn show_personal_stats(&self) -> AocResult<()> {
let stats_html = self.get_personal_stats_html()?;
let stats_text = self.html2text(&stats_html);

// print explanatory paragraph before recoloring the text
for line in stats_text.lines().take_while(|line| !line.is_empty()) {
println!("{}", line);
}

let stats_text = stats_text
.replace(
"--------Part 1---------",
&"--------Part 1---------".color(SILVER).to_string(),
)
.replace(
"--------Part 2---------",
&"--------Part 2---------".color(GOLD).to_string(),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the size of these headers can vary, and they will not be correctly coloured if they're not exactly the same size as in these strings

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad! Maybe a regex would be a better fit here?

)
.replace("Time", &"Time".color(GOLD).to_string())
.replace("Rank", &"Rank".color(GOLD).to_string())
.replace("Score", &"Score".color(GOLD).to_string())
.replacen("Time", &"Time".color(SILVER).to_string(), 1)
.replacen("Rank", &"Rank".color(SILVER).to_string(), 2) // "Rank" also in explanation
.replacen("Score", &"Score".color(SILVER).to_string(), 2); // "Score" also in
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The words in the header are not being coloured as you printed them before (on lines 465-466). We can probably leave the explanation uncoloured though

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for being unclear in the comments, it was my intention for the explanation to remain uncolored since that is the behavior displayed on the website.

// explanation

// just print out the day by day stats, expalanatory paragraph is recolored now
for line in stats_text.lines().skip_while(|line| !line.is_empty()) {
println!("{}", line);
}

Ok(())
}

fn get_private_leaderboard(
&self,
leaderboard_id: LeaderboardId,
Expand Down
4 changes: 4 additions & 0 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,8 @@ pub enum Command {
/// Private leaderboard ID
leaderboard_id: LeaderboardId,
},

/// Show personal stats
#[command(visible_alias = "pe")]
PersonalStats,
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ fn run(args: &Args, client: AocClient) -> AocResult<()> {
}
Ok(())
}
Some(Command::PersonalStats) => client.show_personal_stats(),
Some(Command::Submit { part, answer }) => {
client.submit_answer_and_show_outcome(part, answer)
}
Expand Down