diff --git a/src/main.rs b/src/main.rs index 2927627..5b34112 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ use image::{DynamicImage, RgbaImage}; use tiny_skia::{Paint, PathBuilder, Pixmap, PixmapPaint, Stroke, Transform}; use twitter::*; use wiki::*; +use std::borrow::Cow; static APP_USER_AGENT: &str = concat!( "bot_", @@ -143,25 +144,41 @@ fn do_list_tweets() -> StdError<()> { )? .json::()?; - let id = user["id"].as_u64().unwrap(); - - let timeline: serde_json::Value = twitter_api( - reqwest::Url::parse_with_params( - &TwitterEndpoint::UserTimeline.to_string(), - [ - ("count", "200"), - ("exclude_replies", "true"), - ("include_retweets", "false"), - ("trim_user", "true"), - ("user_id", id.to_string().as_ref()), - ], - )?, - Some(&user_token), - APIAction::Get, - &[], - )? - .json()?; - for tweet in timeline.as_array().unwrap() { + let id = user["id"].as_u64().unwrap().to_string(); + let mut timeline = vec!(); + let mut last_id: Option = None; + loop { + event!(Level::INFO, last_id, "Fetching chunk of tweets..."); + let mut params: Vec<(&str, Cow)> = vec!( + ("count", "200".into()), + ("exclude_replies", "true".into()), + ("include_rts", "false".into()), + ("trim_user", "true".into()), + ("user_id", Cow::Borrowed(&id)), + ); + if let Some(since_id) = last_id { + // Get next chunk of tweets before those we've fetched + params.push(("max_id", (since_id - 1).to_string().into())) + } + let timeline_chunk = twitter_api( + reqwest::Url::parse_with_params( + &TwitterEndpoint::UserTimeline.to_string(), + params, + )?, + Some(&user_token), + APIAction::Get, + &[], + )? + .json::()?; + let chunk = timeline_chunk.as_array().unwrap().to_owned(); + event!(Level::INFO, count=chunk.len(), "Got tweets."); + if chunk.len() == 0 { + break; + } + last_id = Some(chunk.last().unwrap().as_object().unwrap()["id"].as_u64().unwrap()); + timeline.extend(chunk); + } + for tweet in timeline { let tweet = tweet.as_object().unwrap(); println!("{}, \"{}\"", tweet["id"], tweet["text"]); }