summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Tay <sam.chong.tay@gmail.com>2020-06-04 02:26:30 -0700
committerSam Tay <sam.chong.tay@gmail.com>2020-06-04 02:26:30 -0700
commite4946de268a7b963a234ef43b374d27e0eb3700f (patch)
treed31df917dee39becc8c0642ad5f85ce58aeb7de2
parent224547551bd7b525fd9f8c0d137c593a143d0008 (diff)
Stash reqwest progress
-rw-r--r--Cargo.toml3
-rw-r--r--TODO.md1
-rw-r--r--roadmap.md3
-rw-r--r--src/config.rs21
-rw-r--r--src/main.rs61
-rw-r--r--src/stackexchange.rs59
6 files changed, 139 insertions, 9 deletions
diff --git a/Cargo.toml b/Cargo.toml
index e7411ec..e4f3487 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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"] }
diff --git a/TODO.md b/TODO.md
index ab6b703..a05b026 100644
--- a/TODO.md
+++ b/TODO.md
@@ -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
diff --git a/roadmap.md b/roadmap.md
index b1aa414..710bc15 100644
--- a/roadmap.md
+++ b/roadmap.md
@@ -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)
+ }
+}