diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..c3a09fc --- /dev/null +++ b/src/main.rs @@ -0,0 +1,66 @@ +#[allow(unused_imports)] +#[macro_use] +extern crate serde_derive; + +use std::error::Error; +use std::fmt; +use std::iter; +use std::iter::Chain; +use std::thread; +use std::time::Duration; + +mod model; + +use crate::model::*; + +fn main() { + let comments = Comments::for_user("shim__"); + for comment in comments { + dbg!(comment); + thread::sleep(Duration::from_millis(100)); + } + println!("Hello, world!"); +} + +/*fn fetch_comments<'a, T: AsRef + fmt::Display>( + redditor: &'a T, + from: Option, +) -> std::iter::Chain< + std::result::Result< + std::vec::Vec, + std::boxed::Box<(dyn std::error::Error + 'static)>, + >, + std::vec::Vec, +> { + fn request_paged(url: &str) -> Result<(Vec, Option), Box> { + let comment_json = reqwest::get(url)?.text()?; + + let continuation: Option = unimplemented!(); + let comments: Vec = unimplemented!(); + return Ok((comments, continuation)); + } + let page = request_paged(&format!("https://reddit.com/user/{}.json", redditor)); + let next: std::iter::Chain< + std::result::Result< + std::vec::Vec, + std::boxed::Box<(dyn std::error::Error + 'static)>, + >, + std::vec::Vec, + > = if let Ok((_, cont)) = page { + fetch_comments(redditor, cont) + } else { + unimplemented!() //iter::once(Vec::with_capacity(0).iter()).chain([].into_iter().map(|_| fetch_comments("never_gonna_happen", None))) + }; + iter::once([()].into_iter().map(|_| page)).chain([()].into_iter().flat_map(|_| next)) +}*/ + +fn poll(interval: Duration, count: Option) { + let mut it: u32 = 0; + loop { + thread::sleep(interval); + it += 1; + if count.map(|c| c < it).unwrap_or(false) { + break; + } + } +} diff --git a/src/model.rs b/src/model.rs index 8013b08..c7ad12e 100644 --- a/src/model.rs +++ b/src/model.rs @@ -1,6 +1,7 @@ -use serde::{Deserialize, Serialize}; +use serde::de; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_json::Value; use std::error::Error; - use std::iter; use std::iter::Chain; @@ -8,11 +9,32 @@ use std::iter::Chain; pub struct Comment { score: u32, id: String, - created: u64, + created: f64, permalink: String, - edited: bool, + #[serde(deserialize_with = "false_or_val")] + edited: Option, } +fn false_or_val<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let val = Value::deserialize(deserializer)?; + use serde_json::Value::*; + Ok(match val { + Number(num) => num.as_u64(), + Bool(true) => Some(1), + _ => None, + }) +} + +/* +#[derive(Serialize, Deserialize, Debug)] +pub struct ListItem Deserialize<'a>> { + kind: String, + data: T, +}*/ + pub struct Comments { pub url: String, continuation: Option, @@ -20,7 +42,7 @@ pub struct Comments { } impl Comments { - fn new(url: T) -> Comments { + pub fn new(url: T) -> Comments { let url = url.to_string(); Comments { url: url, @@ -28,6 +50,13 @@ impl Comments { buffer: None, } } + + pub fn for_user(name: T) -> Comments { + Self::new(format!( + "https://www.reddit.com/user/{}.json", + name.to_string() + )) + } } impl Iterator for Comments { @@ -35,11 +64,28 @@ impl Iterator for Comments { fn next(&mut self) -> Option { fn request_paged(url: &str) -> Result<(Vec, Option), Box> { - let comment_json = reqwest::get(url)?.text()?; - - let continuation: Option = unimplemented!(); - let comments: Vec = unimplemented!(); - return Ok((comments, continuation)); + dbg!(("Requesting", url)); + let comment_json = dbg!(reqwest::get(url)?.text()?); + let comment_json: Value = serde_json::from_str(&comment_json)?; + let data: &Value = &comment_json["data"]; + let continuation: Option = match &data["after"] { + Value::String(after) => Some(after.clone()), + _ => None, + }; + //Kinda ugly .clone() + //let comments: Vec> = serde_json::from_value(data["children"].clone())?; + if let Some(children) = data["children"].as_array() { + let comments = children + .iter() + .map(|li| serde_json::from_value::(li["data"].clone())) + .collect::, _>>(); + comments + .map(|comments| (comments, continuation)) + .map_err(|e| e.into()) + } else { + Err("Parse err".into()) + } + //return Ok((comments.iter().map(|li| li.data).collect(), continuation)); } if let (Some(ref mut buffer), ref mut continuation, ref url) =