From 14783fb101c8358284178dc8931085e0de6c6067 Mon Sep 17 00:00:00 2001 From: Chaya Danzinger Date: Sat, 24 Nov 2018 21:23:39 -0500 Subject: [PATCH 1/7] add missing auth token warning --- src/lib.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c52a666..d123754 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -103,6 +103,9 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { if let Some(ref token) = config.token { builder.set_authorization_token(token.to_owned()); } + else { + println!("Authentication Warning: You have not provided an auth token and are liimted to 60 requests per hour. Provide an auth token by running the program with '--token ' for 5000 requests per hour."); + } let client = builder.build()?; @@ -120,9 +123,9 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { } } - for star in stars.iter() { - println!("{}", star); - } + // for star in stars.iter() { + // println!("{}", star); + // } println!("Collected {} stars", stars.len()); Ok(()) From 4bda7c437da39b833cb334257c93fbc25b65abe9 Mon Sep 17 00:00:00 2001 From: Chaya Danzinger Date: Tue, 27 Nov 2018 11:08:17 -0500 Subject: [PATCH 2/7] add rate limit warnings --- src/lib.rs | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d123754..4503275 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,10 +4,11 @@ extern crate reqwest; extern crate serde_derive; extern crate serde_json; -use chrono::{DateTime, Utc}; +use chrono::{DateTime, Utc, Local}; use reqwest::header::{qitem, Accept, Authorization, Bearer, Link, RelationType, UserAgent}; use serde_derive::Deserialize; use std::{error, fmt, mem}; +use std::time::{UNIX_EPOCH, Duration}; #[derive(Debug)] pub struct Config { @@ -116,6 +117,7 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { while next_link.is_some() { if let Some(link) = next_link { let mut res = client.get(&link).send()?; + next_link = extract_link_next(res.headers()); let mut s: Vec = res.json()?; @@ -123,15 +125,45 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { } } - // for star in stars.iter() { - // println!("{}", star); - // } + for star in stars.iter() { + println!("{}", star); + } println!("Collected {} stars", stars.len()); Ok(()) } fn extract_link_next(headers: &reqwest::header::Headers) -> Option { + let total_rate_limit = "X-RateLimit-Limit"; + let rate_limit_remaining = "X-RateLimit-Remaining"; + let rate_limit_reset_time = "X-RateLimit-Reset"; + + let mut remaining: i32 = 0; + let mut total: i32 = 0; + + for header in headers.iter() { + if header.name() == total_rate_limit { + total = header.value_string().parse::().unwrap(); + } + if header.name() == rate_limit_remaining { + remaining = header.value_string().parse::().unwrap(); + } + if header.name() == rate_limit_reset_time { + let reset_time = header.value_string(); + let timestamp = reset_time.parse::().unwrap(); + + // Creates a new SystemTime from the specified number of whole seconds + let d = UNIX_EPOCH + Duration::from_secs(timestamp); + + // Create DateTime from SystemTime + let datetime = DateTime::::from(d); + + // Formats the combined date and time with the specified format string. + let timestamp_str = datetime.format("%Y-%m-%d %I:%M").to_string(); + println!{"You have {} out of {} requests remaining. Your request limit will reset at {}", remaining, total, timestamp_str}; + } + } + let link_headers = headers.get::(); match link_headers { From 78a8350358d8591ba900c018be661655b3a9c364 Mon Sep 17 00:00:00 2001 From: Chaya Danzinger Date: Tue, 27 Nov 2018 11:13:31 -0500 Subject: [PATCH 3/7] change wording of warning message --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 4503275..4481246 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -105,7 +105,7 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { builder.set_authorization_token(token.to_owned()); } else { - println!("Authentication Warning: You have not provided an auth token and are liimted to 60 requests per hour. Provide an auth token by running the program with '--token ' for 5000 requests per hour."); + println!("Authentication Warning: This is an unauthenticated request with a limit of 60 requests per hour. Re-run this program using an auth token by adding `--token ` for an increased quota of 5000 requests per hour.") } let client = builder.build()?; From e3b6bd9a1f169a6cf0a99c6ae5cd3d73137a732d Mon Sep 17 00:00:00 2001 From: Chaya Danzinger Date: Tue, 27 Nov 2018 18:05:10 -0500 Subject: [PATCH 4/7] added some error checking code --- src/lib.rs | 74 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4481246..2fa6292 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ use reqwest::header::{qitem, Accept, Authorization, Bearer, Link, RelationType, use serde_derive::Deserialize; use std::{error, fmt, mem}; use std::time::{UNIX_EPOCH, Duration}; +use reqwest::StatusCode; #[derive(Debug)] pub struct Config { @@ -114,12 +115,48 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { let mut next_link = config.url(); + let total_rate_limit = "X-RateLimit-Limit"; + let rate_limit_remaining = "X-RateLimit-Remaining"; + let rate_limit_reset_time = "X-RateLimit-Reset"; + + let mut remaining: i32 = 0; + let mut total: i32 = 0; + let mut timestamp_str = String::new(); while next_link.is_some() { if let Some(link) = next_link { let mut res = client.get(&link).send()?; - next_link = extract_link_next(res.headers()); + for header in res.headers().iter() { + if header.name() == total_rate_limit { + total = header.value_string().parse::().unwrap(); + } + if header.name() == rate_limit_remaining { + remaining = header.value_string().parse::().unwrap(); + } + if header.name() == rate_limit_reset_time { + let reset_time = header.value_string(); + let timestamp = reset_time.parse::().unwrap(); + + // Creates a new SystemTime from the specified number of whole seconds + let d = UNIX_EPOCH + Duration::from_secs(timestamp); + + // Create DateTime from SystemTime + let datetime = DateTime::::from(d); + + // Formats the combined date and time with the specified format string. + timestamp_str = datetime.format("%Y-%m-%d %I:%M").to_string(); + } + } + + match res.status() { + StatusCode::Forbidden => { + return Err(format!("Uh-oh! You have {} out of {} requests remaining. Your request limit will reset at {}", remaining, total, timestamp_str).into()); + }, + s => (), + } + next_link = extract_link_next(res.headers()); + let mut s: Vec = res.json()?; stars.append(&mut s); } @@ -130,40 +167,15 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { } println!("Collected {} stars", stars.len()); + match remaining { + 10 | 0...5 => println!("Warning: You have {} out of {} requests remaining. Your request limit will reset at {}", remaining, total, timestamp_str), + _ => (), + } + Ok(()) } fn extract_link_next(headers: &reqwest::header::Headers) -> Option { - let total_rate_limit = "X-RateLimit-Limit"; - let rate_limit_remaining = "X-RateLimit-Remaining"; - let rate_limit_reset_time = "X-RateLimit-Reset"; - - let mut remaining: i32 = 0; - let mut total: i32 = 0; - - for header in headers.iter() { - if header.name() == total_rate_limit { - total = header.value_string().parse::().unwrap(); - } - if header.name() == rate_limit_remaining { - remaining = header.value_string().parse::().unwrap(); - } - if header.name() == rate_limit_reset_time { - let reset_time = header.value_string(); - let timestamp = reset_time.parse::().unwrap(); - - // Creates a new SystemTime from the specified number of whole seconds - let d = UNIX_EPOCH + Duration::from_secs(timestamp); - - // Create DateTime from SystemTime - let datetime = DateTime::::from(d); - - // Formats the combined date and time with the specified format string. - let timestamp_str = datetime.format("%Y-%m-%d %I:%M").to_string(); - println!{"You have {} out of {} requests remaining. Your request limit will reset at {}", remaining, total, timestamp_str}; - } - } - let link_headers = headers.get::(); match link_headers { From ba7c8691135066a96b66d69b6846ea6c71637f5d Mon Sep 17 00:00:00 2001 From: Chaya Danzinger Date: Wed, 28 Nov 2018 21:31:33 -0500 Subject: [PATCH 5/7] change match s=> to _=> --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 2fa6292..e2736fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -152,7 +152,7 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { StatusCode::Forbidden => { return Err(format!("Uh-oh! You have {} out of {} requests remaining. Your request limit will reset at {}", remaining, total, timestamp_str).into()); }, - s => (), + _ => (), } next_link = extract_link_next(res.headers()); From 489baae134e3cc33ba37c8ee70def75b693a0935 Mon Sep 17 00:00:00 2001 From: Chaya Danzinger Date: Tue, 18 Dec 2018 14:02:33 -0500 Subject: [PATCH 6/7] made requested changes from PR review --- src/lib.rs | 59 +++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e2736fe..d6dc9b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,12 +4,14 @@ extern crate reqwest; extern crate serde_derive; extern crate serde_json; -use chrono::{DateTime, Utc, Local}; +use chrono::{DateTime, Utc}; use reqwest::header::{qitem, Accept, Authorization, Bearer, Link, RelationType, UserAgent}; +use reqwest::StatusCode; use serde_derive::Deserialize; +use std::time::{UNIX_EPOCH, Duration, SystemTime}; use std::{error, fmt, mem}; -use std::time::{UNIX_EPOCH, Duration}; -use reqwest::StatusCode; + + #[derive(Debug)] pub struct Config { @@ -18,7 +20,7 @@ pub struct Config { } impl Config { - fn url(self) -> Option { + fn url(self) -> Option { Some(format!( "https://api.github.com/users/{}/starred", self.username @@ -101,12 +103,13 @@ impl fmt::Display for Repository { pub fn collect_stars(config: Config) -> Result<(), Box> { let mut builder = ClientBuilder::new(); + let mut print_auth_warning = false; if let Some(ref token) = config.token { builder.set_authorization_token(token.to_owned()); } else { - println!("Authentication Warning: This is an unauthenticated request with a limit of 60 requests per hour. Re-run this program using an auth token by adding `--token ` for an increased quota of 5000 requests per hour.") + print_auth_warning = true; } let client = builder.build()?; @@ -114,43 +117,37 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { let mut stars: Vec = Vec::new(); let mut next_link = config.url(); - - let total_rate_limit = "X-RateLimit-Limit"; - let rate_limit_remaining = "X-RateLimit-Remaining"; - let rate_limit_reset_time = "X-RateLimit-Reset"; let mut remaining: i32 = 0; let mut total: i32 = 0; - let mut timestamp_str = String::new(); + let mut reset_time = SystemTime::now(); + while next_link.is_some() { if let Some(link) = next_link { let mut res = client.get(&link).send()?; for header in res.headers().iter() { - if header.name() == total_rate_limit { - total = header.value_string().parse::().unwrap(); - } - if header.name() == rate_limit_remaining { - remaining = header.value_string().parse::().unwrap(); - } - if header.name() == rate_limit_reset_time { - let reset_time = header.value_string(); - let timestamp = reset_time.parse::().unwrap(); + match header.name() { + "X-RateLimit-Limit" => { + total = header.value_string().parse::()?; + }, + "X-RateLimit-Remaining" => { + remaining = header.value_string().parse::()?; + }, + "X-RateLimit-Reset" => { + let seconds = header.value_string().parse::()?; // Creates a new SystemTime from the specified number of whole seconds - let d = UNIX_EPOCH + Duration::from_secs(timestamp); - - // Create DateTime from SystemTime - let datetime = DateTime::::from(d); - - // Formats the combined date and time with the specified format string. - timestamp_str = datetime.format("%Y-%m-%d %I:%M").to_string(); + reset_time = UNIX_EPOCH + Duration::from_secs(seconds); + }, + _ =>(), } } match res.status() { StatusCode::Forbidden => { - return Err(format!("Uh-oh! You have {} out of {} requests remaining. Your request limit will reset at {}", remaining, total, timestamp_str).into()); + //this type of err, or panic? + return Err(format!("Uh-oh! You have {} out of {} requests remaining. Your request limit will reset in {} minutes.", remaining, total, reset_time.duration_since(SystemTime::now())?.as_secs()/60).into()); }, _ => (), } @@ -167,9 +164,13 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { } println!("Collected {} stars", stars.len()); + if print_auth_warning { + eprintln!("\nRequest completed without authentication, re-run and provide token using `--token ` to increase your requests from 60 to 5000 requests per hour."); + } + match remaining { - 10 | 0...5 => println!("Warning: You have {} out of {} requests remaining. Your request limit will reset at {}", remaining, total, timestamp_str), - _ => (), + 10 | 0...5 => eprintln!("Warning: You have {} out of {} requests remaining. Your request limit will reset in {} minutes.", remaining, total, reset_time.duration_since(SystemTime::now())?.as_secs()/60), + _ => println!("Warning: You have {} out of {} requests remaining. Your request limit will reset in {} minutes.", remaining, total, reset_time.duration_since(SystemTime::now())?.as_secs()/60), } Ok(()) From 13463f31d14a15a142f4f084df4ec9f2c5675ec1 Mon Sep 17 00:00:00 2001 From: Chaya Danzinger Date: Wed, 19 Dec 2018 13:23:45 -0500 Subject: [PATCH 7/7] fixed nit reviews --- src/lib.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d6dc9b7..0127c35 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,11 +8,9 @@ use chrono::{DateTime, Utc}; use reqwest::header::{qitem, Accept, Authorization, Bearer, Link, RelationType, UserAgent}; use reqwest::StatusCode; use serde_derive::Deserialize; -use std::time::{UNIX_EPOCH, Duration, SystemTime}; +use std::time::{UNIX_EPOCH, SystemTime, Duration}; use std::{error, fmt, mem}; - - #[derive(Debug)] pub struct Config { username: String, @@ -20,7 +18,7 @@ pub struct Config { } impl Config { - fn url(self) -> Option { + fn url(self) -> Option { Some(format!( "https://api.github.com/users/{}/starred", self.username @@ -120,7 +118,7 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { let mut remaining: i32 = 0; let mut total: i32 = 0; - let mut reset_time = SystemTime::now(); + let mut mins = 0; while next_link.is_some() { if let Some(link) = next_link { @@ -138,7 +136,8 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { let seconds = header.value_string().parse::()?; // Creates a new SystemTime from the specified number of whole seconds - reset_time = UNIX_EPOCH + Duration::from_secs(seconds); + let reset_time = UNIX_EPOCH + Duration::from_secs(seconds); + mins = reset_time.duration_since(SystemTime::now())?.as_secs()/60; }, _ =>(), } @@ -146,8 +145,7 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { match res.status() { StatusCode::Forbidden => { - //this type of err, or panic? - return Err(format!("Uh-oh! You have {} out of {} requests remaining. Your request limit will reset in {} minutes.", remaining, total, reset_time.duration_since(SystemTime::now())?.as_secs()/60).into()); + return Err(format!("Uh-oh! You have {} out of {} requests remaining. Your request limit will reset in {} minutes.", remaining, total, mins).into()); }, _ => (), } @@ -169,8 +167,8 @@ pub fn collect_stars(config: Config) -> Result<(), Box> { } match remaining { - 10 | 0...5 => eprintln!("Warning: You have {} out of {} requests remaining. Your request limit will reset in {} minutes.", remaining, total, reset_time.duration_since(SystemTime::now())?.as_secs()/60), - _ => println!("Warning: You have {} out of {} requests remaining. Your request limit will reset in {} minutes.", remaining, total, reset_time.duration_since(SystemTime::now())?.as_secs()/60), + 10 | 0...5 => eprintln!("Warning: You have {} out of {} requests remaining. Your request limit will reset in {} minutes.", remaining, total, mins), + _ => (), } Ok(())