diff options
author | Sam Tay <sam.chong.tay@gmail.com> | 2020-06-04 02:26:30 -0700 |
---|---|---|
committer | Sam Tay <sam.chong.tay@gmail.com> | 2020-06-04 02:26:30 -0700 |
commit | e4946de268a7b963a234ef43b374d27e0eb3700f (patch) | |
tree | d31df917dee39becc8c0642ad5f85ce58aeb7de2 | |
parent | 224547551bd7b525fd9f8c0d137c593a143d0008 (diff) |
Stash reqwest progress
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | TODO.md | 1 | ||||
-rw-r--r-- | roadmap.md | 3 | ||||
-rw-r--r-- | src/config.rs | 21 | ||||
-rw-r--r-- | src/main.rs | 61 | ||||
-rw-r--r-- | src/stackexchange.rs | 59 |
6 files changed, 139 insertions, 9 deletions
@@ -8,3 +8,6 @@ edition = "2018" [dependencies] clap = "2.33.1" +directories = "2.0.2" +reqwest = { version = "0.10.6", features = ["json"] } +tokio = { version = "0.2.21", features = ["full"] } @@ -3,6 +3,7 @@ 2. Hit SO API - [json specs](https://rust-lang-nursery.github.io/rust-cookbook/encoding/complex.html#serialize-and-deserialize-unstructured-json) - [hitting api](https://rust-lang-nursery.github.io/rust-cookbook/web/clients/apis.html) +3. Test if pre-made filter can be used for various api keys 3. Parse markdown ### resources for later @@ -14,6 +14,9 @@ ### v0.2.1 1. Add xdga config +### v0.2.2 +1. Support multiple --site args & searches + ### v0.3.0 1. Add google scraper + helpful error messages diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..d84e7ce --- /dev/null +++ b/src/config.rs @@ -0,0 +1,21 @@ +use directories; + +pub struct Site { + url: String, + code: String, +} + +pub struct Config { + filter: String, + sites: Vec<String>, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_config() { + assert!(true) + } +} diff --git a/src/main.rs b/src/main.rs index 45788c4..5a55bfa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,59 @@ -use clap::clap_app; -use clap::App; +use clap::{App, AppSettings, Arg}; + +mod config; +mod stackexchange; + +// TODO maybe consts for these keywords? // TODO pull defaults from config file +// TODO --set-api-key KEY +// TODO --update-cache +// TODO --install-filter-key --force +//?TODO --set-default-opt opt val # e.g. --set-default-opt sites site1;site2;site3 // may require dropping the macros fn mk_app<'a, 'b>() -> App<'a, 'b> { - clap_app!(so => - (version: clap::crate_version!()) - (author: clap::crate_authors!()) - (about: clap::crate_description!()) - (@arg site: -s --site +takes_value default_value("stackoverflow") "StackExchange site") - (@arg query: ... +required "Query to search") - ) + App::new("so") + .setting(AppSettings::ColoredHelp) + .version(clap::crate_version!()) + .author(clap::crate_authors!()) + .about(clap::crate_description!()) + .arg( + Arg::with_name("list-sites") + .long("list-sites") + .help("Print available StackExchange sites"), + ) + .arg( + Arg::with_name("site") + .long("site") + .short("s") + .multiple(true) + .number_of_values(1) + .takes_value(true) + .default_value("stackoverflow") + .help("StackExchange site codes to search"), + ) + .arg( + Arg::with_name("limit") + .long("limit") + .short("l") + .number_of_values(1) + .takes_value(true) + .default_value("50") + .validator(|s| s.parse::<u32>().map_err(|e| e.to_string()).map(|_| ())) + .help("Question limit per site query"), + ) + .arg( + Arg::with_name("lucky") + .long("lucky") + .help("Print the top-voted answer of the most relevant question"), + ) + .arg( + Arg::with_name("query") + .multiple(true) + .index(1) + .required(true) + .required_unless("list-sites"), + ) } fn main() { diff --git a/src/stackexchange.rs b/src/stackexchange.rs new file mode 100644 index 0000000..84eaa80 --- /dev/null +++ b/src/stackexchange.rs @@ -0,0 +1,59 @@ +use reqwest::Client; + +use crate::config::Config; + +const SE_URL: String = "http://api.stackexchange.com/2.2/"; +const SE_ENDPOINT_SEARCH: String = "search/advanced"; + +struct StackExchange { + client: Client, + config: Config, +} + +struct Question { + id: u32, + score: i32, + answers: Vec<Answer>, + title: String, + body: String, +} + +struct Answer { + id: u32, + score: i32, + body: String, + accepted: bool, +} + +impl StackExchange { + pub fn new(config: Config) -> Self { + let client = Client::new(); + StackExchange { client, config } + } + + // https://stackoverflow.com/a/57770687 is the right way to do this + pub fn query(q: &str) -> Result<Vec<Question>, String> { + let request_url = format!( + "{url}{endpoint}", + url = SE_URL, + endpoint = SE_ENDPOINT_SEARCH + ); + println!("{}", request_url); + let mut response = reqwest::get(&request_url)?; + + let users: Vec<User> = response.json()?; + println!("{:?}", users); + Ok(()) + //Err("Not implemented".to_string()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_stackexchange() { + assert!(true) + } +} |