From e4925f0311574cd954909695bb587902179f8680 Mon Sep 17 00:00:00 2001 From: Andy Wortman Date: Sat, 25 Nov 2017 18:39:04 -0800 Subject: extract DisplayInfo from TwitterCache what a mess... threading this through to any point where printing happens is upsetting. probably should be a global mutable behind accessors. --- src/commands/auth.rs | 23 +++++----- src/commands/fav.rs | 21 ++++----- src/commands/follow.rs | 11 ++--- src/commands/help.rs | 3 +- src/commands/look_up.rs | 19 +++++---- src/commands/mod.rs | 3 +- src/commands/profile.rs | 9 ++-- src/commands/quit.rs | 3 +- src/commands/show_cache.rs | 17 ++++---- src/commands/thread.rs | 19 +++++---- src/commands/twete.rs | 85 ++++++++++++++++++------------------ src/commands/view.rs | 23 +++++----- src/display/mod.rs | 67 +++++++++++++++-------------- src/main.rs | 99 +++++++++++++++++++++--------------------- src/tw/mod.rs | 104 +++++++++++++++++++++++---------------------- 15 files changed, 263 insertions(+), 243 deletions(-) diff --git a/src/commands/auth.rs b/src/commands/auth.rs index db3a143..9b83c66 100644 --- a/src/commands/auth.rs +++ b/src/commands/auth.rs @@ -1,3 +1,4 @@ +use display::DisplayInfo; use tw; use std; use std::collections::HashMap; @@ -22,7 +23,7 @@ static OAUTH_REQUEST_TOKEN_URL: &str = "https://api.twitter.com/oauth/request_to static OAUTH_AUTHORIZE_URL: &str = "https://api.twitter.com/oauth/authorize"; static OAUTH_ACCESS_TOKEN_URL: &str = "https://api.twitter.com/oauth/access_token"; -fn auth(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn auth(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { // step 0: get an oauth token. // https://developer.twitter.com/en/docs/basics/authentication/api-reference/request_token with // callback set to oob so the user will later get a PIN. @@ -42,13 +43,13 @@ fn auth(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { key: as_map["oauth_token"].to_owned(), secret: as_map["oauth_token_secret"].to_owned() }); - tweeter.display_info.status(format!("Now enter `pin` with the code at {}?oauth_token={}", OAUTH_AUTHORIZE_URL, as_map["oauth_token"])); + display_info.status(format!("Now enter `pin` with the code at {}?oauth_token={}", OAUTH_AUTHORIZE_URL, as_map["oauth_token"])); } Err(_) => - tweeter.display_info.status("couldn't rebuild url".to_owned()) + display_info.status("couldn't rebuild url".to_owned()) }, Err(e) => - tweeter.display_info.status(format!("request token url error: {}", e)) + display_info.status(format!("request token url error: {}", e)) }; } @@ -60,9 +61,9 @@ pub static PIN: Command = Command { help_str: "Complete account auth. Enter PIN from prior `auth` link to connect an account." }; -fn pin(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn pin(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { if tweeter.WIP_auth.is_none() { - tweeter.display_info.status("Begin authorizing an account with `auth` first.".to_owned()); + display_info.status("Begin authorizing an account with `auth` first.".to_owned()); return; } @@ -102,20 +103,20 @@ fn pin(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { match queryer.do_api_get(::ACCOUNT_SETTINGS_URL, &tweeter.app_key, &user_credential) { Ok(settings) => { let user_handle = settings["screen_name"].as_str().unwrap().to_owned(); - tweeter.add_profile(tw::TwitterProfile::new(user_credential, tw::user::User::default()), Some(user_handle.clone())); + tweeter.add_profile(tw::TwitterProfile::new(user_credential, tw::user::User::default()), Some(user_handle.clone()), display_info); tweeter.WIP_auth = None; tweeter.state = tw::AppState::Reconnect(user_handle); - tweeter.display_info.status("Looks like you authed! Connecting...".to_owned()); + display_info.status("Looks like you authed! Connecting...".to_owned()); }, Err(_) => { - tweeter.display_info.status("Auth failed - couldn't find your handle.".to_owned()); + display_info.status("Auth failed - couldn't find your handle.".to_owned()); } }; }, Err(_) => - tweeter.display_info.status("couldn't rebuild url".to_owned()) + display_info.status("couldn't rebuild url".to_owned()) }, Err(e) => - tweeter.display_info.status(format!("request token url error: {}", e)) + display_info.status(format!("request token url error: {}", e)) }; } diff --git a/src/commands/fav.rs b/src/commands/fav.rs index e823618..0bee8ce 100644 --- a/src/commands/fav.rs +++ b/src/commands/fav.rs @@ -1,3 +1,4 @@ +use display::DisplayInfo; use tw; use ::Queryer; @@ -16,25 +17,25 @@ pub static UNFAV: Command = Command { help_str: "Unfavorite a tweet." }; -fn unfav(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn unfav(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { let maybe_id = TweetId::parse(line.to_owned()); match maybe_id { Ok(twid) => { - if let Some(twete) = tweeter.retrieve_tweet(&twid).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self + if let Some(twete) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self let result = match tweeter.current_profile() { Some(user_profile) => queryer.do_api_post(&format!("{}?id={}", UNFAV_TWEET_URL, twete.id), &tweeter.app_key, &user_profile.creds), None => Err("No logged in user to unfav from".to_owned()) }; match result { Ok(_) => (), - Err(e) => tweeter.display_info.status(e) + Err(e) => display_info.status(e) } } else { - tweeter.display_info.status(format!("No tweet for id: {:?}", twid)); + display_info.status(format!("No tweet for id: {:?}", twid)); } } Err(e) => { - tweeter.display_info.status(format!("Invalid id: {}", e)); + display_info.status(format!("Invalid id: {}", e)); } } } @@ -47,26 +48,26 @@ pub static FAV: Command = Command { help_str: "Favorite a tweet." }; -fn fav(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn fav(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { let maybe_id = TweetId::parse(line.to_owned()); match maybe_id { Ok(twid) => { // tweeter.to_twitter_tweet_id(twid)... - if let Some(twete) = tweeter.retrieve_tweet(&twid).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self + if let Some(twete) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self let result = match tweeter.current_profile() { Some(user_profile) => queryer.do_api_post(&format!("{}?id={}", FAV_TWEET_URL, twete.id), &tweeter.app_key, &user_profile.creds), None => Err("No logged in user to fav from".to_owned()) }; match result { Ok(_) => (), - Err(e) => tweeter.display_info.status(e) + Err(e) => display_info.status(e) } } else { - tweeter.display_info.status(format!("No tweet for id: {:?}", twid)); + display_info.status(format!("No tweet for id: {:?}", twid)); } } Err(e) => { - tweeter.display_info.status(format!("Invalid id: {}", e)); + display_info.status(format!("Invalid id: {}", e)); } } } diff --git a/src/commands/follow.rs b/src/commands/follow.rs index 6e29788..bc767d5 100644 --- a/src/commands/follow.rs +++ b/src/commands/follow.rs @@ -1,3 +1,4 @@ +use display::DisplayInfo; use tw; use ::Queryer; @@ -14,7 +15,7 @@ pub static UNFOLLOW: Command = Command { help_str: "Unfollow . No @ prefix in !" }; -fn unfl(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn unfl(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { let screen_name = line.trim(); let result = match tweeter.current_profile() { Some(user_profile) => { @@ -24,7 +25,7 @@ fn unfl(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { }; match result { Ok(_resp) => (), - Err(e) => tweeter.display_info.status(format!("unfl request error: {}", e)) + Err(e) => display_info.status(format!("unfl request error: {}", e)) } } @@ -36,11 +37,11 @@ pub static FOLLOW: Command = Command { help_str: "Follow . No @ prefix in !" }; -fn fl(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn fl(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { let screen_name = line.trim(); match tweeter.current_profile().map(|profile| profile.to_owned()) { Some(user_profile) => { - tweeter.display_info.status( + display_info.status( format!( "fl resp: {:?}", queryer.do_api_post( @@ -51,6 +52,6 @@ fn fl(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { ) ) }, - None => tweeter.display_info.status("No logged in user to follow from".to_owned()) + None => display_info.status("No logged in user to follow from".to_owned()) }; } diff --git a/src/commands/help.rs b/src/commands/help.rs index 445684b..550b677 100644 --- a/src/commands/help.rs +++ b/src/commands/help.rs @@ -1,3 +1,4 @@ +use display::DisplayInfo; use tw; use ::Queryer; @@ -11,6 +12,6 @@ pub static HELP: Command = Command { help_str: "This help prompt." }; -fn help(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn help(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { tweeter.state = tw::AppState::ShowHelp; } diff --git a/src/commands/look_up.rs b/src/commands/look_up.rs index 7bd5885..2674b34 100644 --- a/src/commands/look_up.rs +++ b/src/commands/look_up.rs @@ -1,3 +1,4 @@ +use display::DisplayInfo; use tw; use tw::TweetId; use display; @@ -13,12 +14,12 @@ pub static LOOK_UP_USER: Command = Command { help_str: "Look up the user by the specified twitter user ID, display name/handle." }; -fn look_up_user(line: String, tweeter: &mut tw::TwitterCache, mut queryer: &mut Queryer) { +fn look_up_user(line: String, tweeter: &mut tw::TwitterCache, mut queryer: &mut Queryer, display_info: &mut DisplayInfo) { // should probably just pass the id? - if let Some(user) = tweeter.fetch_user(&line, &mut queryer).map(|x| x.clone()) { - tweeter.display_info.recv(display::Infos::User(user)); + if let Some(user) = tweeter.fetch_user(&line, &mut queryer, display_info).map(|x| x.clone()) { + display_info.recv(display::Infos::User(user)); } else { - tweeter.display_info.status(format!("Couldn't retrieve {}", line)); + display_info.status(format!("Couldn't retrieve {}", line)); } } @@ -31,17 +32,17 @@ pub static LOOK_UP_TWEET: Command = Command { }; // TODO: make this parse a proper tweet id -fn look_up_tweet(line: String, tweeter: &mut tw::TwitterCache, mut queryer: &mut Queryer) { +fn look_up_tweet(line: String, tweeter: &mut tw::TwitterCache, mut queryer: &mut Queryer, display_info: &mut DisplayInfo) { match TweetId::parse(line) { Ok(twid) => { - if let Some(tweet) = tweeter.fetch_tweet(&twid, &mut queryer).map(|x| x.clone()) { - tweeter.display_info.recv(display::Infos::Tweet(twid)); + if let Some(tweet) = tweeter.fetch_tweet(&twid, &mut queryer, display_info).map(|x| x.clone()) { + display_info.recv(display::Infos::Tweet(twid)); } else { - tweeter.display_info.status(format!("Couldn't retrieve {:?}", twid)); + display_info.status(format!("Couldn't retrieve {:?}", twid)); } }, Err(e) => { - tweeter.display_info.status(format!("Invalid id {:?}", e)); + display_info.status(format!("Invalid id {:?}", e)); } } } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 262a748..e8a725b 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,10 +1,11 @@ +use display::DisplayInfo; use tw; use ::Queryer; pub struct Command { pub keyword: &'static str, pub params: u8, - pub exec: fn(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer), + pub exec: fn(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo), pub param_str: &'static str, pub help_str: &'static str } diff --git a/src/commands/profile.rs b/src/commands/profile.rs index c0d5d79..e20859b 100644 --- a/src/commands/profile.rs +++ b/src/commands/profile.rs @@ -1,3 +1,4 @@ +use display::DisplayInfo; use tw; use std; use std::collections::HashMap; @@ -14,12 +15,12 @@ pub static PROFILE: Command = Command { help_str: "Switch to profile " }; -fn switch_profile(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn switch_profile(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { let profile_name = line.trim(); if tweeter.profiles.contains_key(profile_name) { tweeter.curr_profile = Some(profile_name.to_owned()); } else { - tweeter.display_info.status(format!("No profile named {}", profile_name)) + display_info.status(format!("No profile named {}", profile_name)) }; } @@ -31,8 +32,8 @@ pub static PROFILES: Command = Command { help_str: "List all profiles" }; -fn list_profiles(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { - tweeter.display_info.recv(::display::Infos::Text( +fn list_profiles(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { + display_info.recv(::display::Infos::Text( tweeter.profiles.keys().map(|key| key.to_owned()).collect() )); } diff --git a/src/commands/quit.rs b/src/commands/quit.rs index 0f5c582..45390a3 100644 --- a/src/commands/quit.rs +++ b/src/commands/quit.rs @@ -1,3 +1,4 @@ +use display::DisplayInfo; use tw; use ::Queryer; @@ -12,6 +13,6 @@ pub static QUIT: Command = Command { help_str: "Gracefully exit this thing" }; -fn quit(_line: String, tweeter: &mut tw::TwitterCache, _queryer: &mut Queryer) { +fn quit(_line: String, tweeter: &mut tw::TwitterCache, _queryer: &mut Queryer, display_info: &mut DisplayInfo) { tweeter.state = tw::AppState::Shutdown; } diff --git a/src/commands/show_cache.rs b/src/commands/show_cache.rs index 6dda8dc..2b810d7 100644 --- a/src/commands/show_cache.rs +++ b/src/commands/show_cache.rs @@ -1,3 +1,4 @@ +use display::DisplayInfo; use tw; use ::Queryer; @@ -11,24 +12,24 @@ pub static SHOW_CACHE: Command = Command { help_str: "Dump all cached info. Probably a bad idea." }; -fn show_cache(_line: String, tweeter: &mut tw::TwitterCache, mut queryer: &mut Queryer) { +fn show_cache(_line: String, tweeter: &mut tw::TwitterCache, mut queryer: &mut Queryer, display_info: &mut DisplayInfo) { /* - tweeter.display_info.status("----* USERS *----".to_owned()); + display_info.status("----* USERS *----".to_owned()); for (uid, user) in &tweeter.users { - tweeter.display_info.status(format!("User: {} -> {:?}", uid, user)); + display_info.status(format!("User: {} -> {:?}", uid, user)); } - tweeter.display_info.status("----* TWEETS *----".to_owned()); + display_info.status("----* TWEETS *----".to_owned()); for (tid, tweet) in &tweeter.tweets { - tweeter.display_info.status(format!("Tweet: {} -> {:?}", tid, tweet)); + display_info.status(format!("Tweet: {} -> {:?}", tid, tweet)); } - tweeter.display_info.status("----* FOLLOWERS *----".to_owned()); + display_info.status("----* FOLLOWERS *----".to_owned()); for uid in &tweeter.followers.clone() { let user_res = tweeter.fetch_user(uid, &mut queryer).map(|x| x.clone()); match user_res { Some(user) => { - tweeter.display_info.status(format!("Follower: {} - {:?}", uid, user)); + display_info.status(format!("Follower: {} - {:?}", uid, user)); } - None => { tweeter.display_info.status(" ...".to_owned()); } + None => { display_info.status(" ...".to_owned()); } } } */ diff --git a/src/commands/thread.rs b/src/commands/thread.rs index 71d0e52..302e641 100644 --- a/src/commands/thread.rs +++ b/src/commands/thread.rs @@ -1,3 +1,4 @@ +use display::DisplayInfo; use tw; use ::Queryer; use ::display; @@ -14,9 +15,9 @@ pub static FORGET_THREAD: Command = Command { help_str: "Discard thread known by . Entirely local to the client." }; -fn forget(line: String, tweeter: &mut tw::TwitterCache, _queryer: &mut Queryer) { +fn forget(line: String, tweeter: &mut tw::TwitterCache, _queryer: &mut Queryer, display_info: &mut DisplayInfo) { tweeter.forget_thread(line.trim().to_string()); - tweeter.display_info.status(format!("Ok! Forgot thread {}", line.trim().to_string())); + display_info.status(format!("Ok! Forgot thread {}", line.trim().to_string())); } pub static REMEMBER_THREAD: Command = Command { @@ -27,7 +28,7 @@ pub static REMEMBER_THREAD: Command = Command { help_str: "Remember the thread tipped by as . Entirely local to the client." }; -fn remember(line: String, tweeter: &mut tw::TwitterCache, _queryer: &mut Queryer) { +fn remember(line: String, tweeter: &mut tw::TwitterCache, _queryer: &mut Queryer, display_info: &mut DisplayInfo) { let mut text: String = line.trim().to_string(); if let Some(id_end_idx) = text.find(" ") { let name_bare = text.split_off(id_end_idx + 1); @@ -37,15 +38,15 @@ fn remember(line: String, tweeter: &mut tw::TwitterCache, _queryer: &mut Queryer let maybe_id = TweetId::parse(line.to_owned()); match maybe_id { Ok(twid) => { - if let Some(twete) = tweeter.retrieve_tweet(&twid).map(|x| x.clone()) { + if let Some(twete) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.clone()) { tweeter.set_thread(name.to_string(), twete.internal_id); - tweeter.display_info.status(format!("Ok! Recorded {:?} as thread {}", twid, name)); + display_info.status(format!("Ok! Recorded {:?} as thread {}", twid, name)); } else { - tweeter.display_info.status(format!("No tweet for id: {:?}", twid)); + display_info.status(format!("No tweet for id: {:?}", twid)); } } Err(e) => { - tweeter.display_info.status(format!("Invalid id: {}", e)); + display_info.status(format!("Invalid id: {}", e)); } } } @@ -60,10 +61,10 @@ pub static LIST_THREADS: Command = Command { help_str: "Show all known (local) threads" }; -fn ls_threads(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn ls_threads(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { let threads: Vec = tweeter.threads().collect::>().into_iter().map(|x| x.to_owned()).collect::>(); for k in threads { let latest_inner_id = tweeter.latest_in_thread(k.to_owned()).unwrap().to_owned(); - tweeter.display_info.recv(display::Infos::TweetWithContext(TweetId::Bare(latest_inner_id), format!("Thread: {}", k))) + display_info.recv(display::Infos::TweetWithContext(TweetId::Bare(latest_inner_id), format!("Thread: {}", k))) } } diff --git a/src/commands/twete.rs b/src/commands/twete.rs index 0d82b76..ac4bbeb 100644 --- a/src/commands/twete.rs +++ b/src/commands/twete.rs @@ -1,3 +1,4 @@ +use display::DisplayInfo; use tw; use ::Queryer; @@ -17,25 +18,25 @@ pub static DEL: Command = Command { help_str: "Delete tweet " }; -fn del(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn del(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { match TweetId::parse(line.clone()) { Ok(twid) => { // TODO this really converts twid to a TweetId::Twitter - if let Some(twitter_id) = tweeter.retrieve_tweet(&twid).map(|x| x.id.to_owned()) { + if let Some(twitter_id) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.id.to_owned()) { let result = match tweeter.current_profile() { Some(user_profile) => queryer.do_api_post(&format!("{}/{}.json", DEL_TWEET_URL, twitter_id), &tweeter.app_key, &user_profile.creds), None => Err("No logged in user to delete as".to_owned()) }; match result { Ok(_) => (), - Err(e) => tweeter.display_info.status(e) + Err(e) => display_info.status(e) } } else { - tweeter.display_info.status(format!("No tweet for id {:?}", twid)); + display_info.status(format!("No tweet for id {:?}", twid)); } }, Err(e) => { - tweeter.display_info.status(format!("Invalid id: {:?} ({})", line, e)); + display_info.status(format!("Invalid id: {:?} ({})", line, e)); } } } @@ -48,18 +49,18 @@ pub static TWETE: Command = Command { help_str: "Enter tweet compose mode." }; -fn twete(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn twete(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { // if there's text, send it. // if it's just "t", enter compose mode. let text = line.trim().to_owned(); if text.len() == 0 { - tweeter.display_info.mode = Some(::display::DisplayMode::Compose(text)); + display_info.mode = Some(::display::DisplayMode::Compose(text)); } else { - send_twete(text, tweeter, queryer); + send_twete(text, tweeter, queryer, display_info); } } -pub fn send_twete(text: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +pub fn send_twete(text: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { let substituted = ::url_encode(&text); let result = match tweeter.current_profile() { Some(user_profile) => queryer.do_api_post(&format!("{}?status={}", CREATE_TWEET_URL, substituted), &tweeter.app_key, &user_profile.creds), @@ -67,7 +68,7 @@ pub fn send_twete(text: String, tweeter: &mut tw::TwitterCache, queryer: &mut Qu }; match result { Ok(_) => (), - Err(e) => tweeter.display_info.status(e) + Err(e) => display_info.status(e) } } @@ -82,11 +83,11 @@ pub static THREAD: Command = Command { // the difference between threading and replying is not including // yourself in th @'s. -fn thread(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn thread(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { let user_profile = match tweeter.current_profile().map(|profile| profile.to_owned()) { Some(profile) => profile, None => { - tweeter.display_info.status("To reply you must be authenticated as a user.".to_owned()); + display_info.status("To reply you must be authenticated as a user.".to_owned()); return; } }; @@ -99,26 +100,26 @@ fn thread(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { let maybe_id = TweetId::parse(id_str.to_owned()); match maybe_id { Ok(twid) => { - if let Some(twete) = tweeter.retrieve_tweet(&twid).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self + if let Some(twete) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self let handle = &tweeter.retrieve_user(&twete.author_id).unwrap().handle.to_owned(); // TODO: definitely breaks if you change your handle right now if handle == &user_profile.user.handle { - send_reply(reply.to_owned(), twid, tweeter, queryer, user_profile.creds); + send_reply(reply.to_owned(), twid, tweeter, queryer, user_profile.creds, display_info); } else { - tweeter.display_info.status("you can only thread your own tweets".to_owned()); + display_info.status("you can only thread your own tweets".to_owned()); // ask if it should .@ instead? } } } Err(e) => { - tweeter.display_info.status(format!("Invalid id: {}", e)); + display_info.status(format!("Invalid id: {}", e)); } } } else { - tweeter.display_info.status("thread your sik reply".to_owned()); + display_info.status("thread your sik reply".to_owned()); } } else { - tweeter.display_info.status("thread your sik reply".to_owned()); + display_info.status("thread your sik reply".to_owned()); } } @@ -131,11 +132,11 @@ pub static REP: Command = Command { help_str: "Enter compose mode to reply to " }; -fn rep(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn rep(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { let user_profile = match tweeter.current_profile().map(|profile| profile.to_owned()) { Some(profile) => profile, None => { - tweeter.display_info.status("To reply you must be authenticated as a user.".to_owned()); + display_info.status("To reply you must be authenticated as a user.".to_owned()); return; } }; @@ -151,13 +152,13 @@ fn rep(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { let maybe_id = TweetId::parse(id_str.to_owned()); match maybe_id { Ok(twid) => { - if let Some(twete) = tweeter.retrieve_tweet(&twid).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self + if let Some(twete) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self // get handles to reply to... let author_handle = tweeter.retrieve_user(&twete.author_id).unwrap().handle.to_owned(); let mut ats: Vec = twete.get_mentions(); //std::collections::HashSet::new(); ats.remove_item(&author_handle); ats.insert(0, author_handle); - if let Some(rt_tweet) = twete.rt_tweet.and_then(|id| tweeter.retrieve_tweet(&TweetId::Twitter(id))).map(|x| x.clone()) { + if let Some(rt_tweet) = twete.rt_tweet.and_then(|id| tweeter.retrieve_tweet(&TweetId::Twitter(id), display_info)).map(|x| x.clone()) { let rt_author_handle = tweeter.retrieve_user(&rt_tweet.author_id).unwrap().handle.to_owned(); ats.remove_item(&rt_author_handle); ats.insert(1, rt_author_handle); @@ -175,22 +176,22 @@ fn rep(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { let full_reply = format!("{} {}", decorated_ats.join(" "), reply); if reply.len() > 0 { - send_reply(full_reply, twid, tweeter, queryer, user_profile.creds); + send_reply(full_reply, twid, tweeter, queryer, user_profile.creds, display_info); } else { - tweeter.display_info.mode = Some(::display::DisplayMode::Reply(twid, full_reply)); + display_info.mode = Some(::display::DisplayMode::Reply(twid, full_reply)); } } else { - tweeter.display_info.status(format!("No tweet for id: {:?}", twid)); + display_info.status(format!("No tweet for id: {:?}", twid)); } }, Err(e) => { - tweeter.display_info.status(format!("Cannot parse input: {:?} ({})", id_str, e)); + display_info.status(format!("Cannot parse input: {:?} ({})", id_str, e)); } } } -pub fn send_reply(text: String, twid: TweetId, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, user_creds: tw::Credential) { - if let Some(twete) = tweeter.retrieve_tweet(&twid).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self +pub fn send_reply(text: String, twid: TweetId, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, user_creds: tw::Credential, display_info: &mut DisplayInfo) { + if let Some(twete) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self let substituted = ::url_encode(&text); let result = match tweeter.current_profile() { Some(user_profile) => { @@ -200,10 +201,10 @@ pub fn send_reply(text: String, twid: TweetId, tweeter: &mut tw::TwitterCache, q }; match result { Ok(_) => (), - Err(e) => tweeter.display_info.status(e) + Err(e) => display_info.status(e) } } else { - tweeter.display_info.status(format!("Tweet stopped existing: {:?}", twid)); + display_info.status(format!("Tweet stopped existing: {:?}", twid)); } } @@ -215,7 +216,7 @@ pub static QUOTE: Command = Command { help_str: "Quote with context " }; -fn quote(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn quote(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { let mut text: String = line.trim().to_string(); if let Some(id_end_idx) = text.find(" ") { let reply_bare = text.split_off(id_end_idx + 1); @@ -225,7 +226,7 @@ fn quote(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { let maybe_id = TweetId::parse(id_str.to_owned()); match maybe_id { Ok(twid) => { - if let Some(twete) = tweeter.retrieve_tweet(&twid).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self + if let Some(twete) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self let substituted = ::url_encode(reply); let attachment_url = ::url_encode( &format!( @@ -250,21 +251,21 @@ fn quote(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { }; match result { Ok(_) => (), - Err(e) => tweeter.display_info.status(e) + Err(e) => display_info.status(e) } } else { - tweeter.display_info.status(format!("No tweet found for id {:?}", twid)); + display_info.status(format!("No tweet found for id {:?}", twid)); } }, Err(e) => { - tweeter.display_info.status(format!("Invalid id: {:?}", id_str)); + display_info.status(format!("Invalid id: {:?}", id_str)); } } } else { - tweeter.display_info.status("rep your sik reply".to_owned()); + display_info.status("rep your sik reply".to_owned()); } } else { - tweeter.display_info.status("rep your sik reply".to_owned()); + display_info.status("rep your sik reply".to_owned()); } } @@ -276,11 +277,11 @@ pub static RETWETE: Command = Command { help_str: "Retweet " }; -fn retwete(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn retwete(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { match TweetId::parse(line.clone()) { Ok(twid) => { // TODO this really converts twid to a TweetId::Twitter - if let Some(twitter_id) = tweeter.retrieve_tweet(&twid).map(|x| x.id.to_owned()) { + if let Some(twitter_id) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.id.to_owned()) { let result = match tweeter.current_profile() { Some(user_profile) => { queryer.do_api_post(&format!("{}/{}.json", RT_TWEET_URL, twitter_id), &tweeter.app_key, &user_profile.creds) @@ -289,14 +290,14 @@ fn retwete(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) }; match result { Ok(_) => (), - Err(e) => tweeter.display_info.status(e) + Err(e) => display_info.status(e) } } else { - tweeter.display_info.status(format!("No tweet for id {:?}", twid)); + display_info.status(format!("No tweet for id {:?}", twid)); } }, Err(e) => { - tweeter.display_info.status(format!("Invalid id: {:?}", line)); + display_info.status(format!("Invalid id: {:?}", line)); } } } diff --git a/src/commands/view.rs b/src/commands/view.rs index 15c94b1..41dd9b3 100644 --- a/src/commands/view.rs +++ b/src/commands/view.rs @@ -1,3 +1,4 @@ +use display::DisplayInfo; use tw; use ::Queryer; @@ -15,20 +16,20 @@ pub static VIEW: Command = Command { help_str: "Display tweet with a reference URL" }; -fn view(line: String, tweeter: &mut tw::TwitterCache, _queryer: &mut Queryer) { +fn view(line: String, tweeter: &mut tw::TwitterCache, _queryer: &mut Queryer, display_info: &mut DisplayInfo) { match TweetId::parse(line) { Ok(twid) => { - if let Some(twete) = tweeter.retrieve_tweet(&twid).map(|x| x.clone()) { - tweeter.display_info.recv(display::Infos::TweetWithContext( + if let Some(twete) = tweeter.retrieve_tweet(&twid, display_info) { + display_info.recv(display::Infos::TweetWithContext( TweetId::Twitter(twete.id.to_owned()), format!("link: https://twitter.com/i/web/status/{}", twete.id) )); } else { - tweeter.display_info.status(format!("No tweet for id {:?}", twid)); + display_info.status(format!("No tweet for id {:?}", twid)); } }, Err(e) => { - tweeter.display_info.status(format!("Invalid id {:?}", e)); + display_info.status(format!("Invalid id {:?}", e)); } } } @@ -41,28 +42,28 @@ pub static VIEW_THREAD: Command = Command { help_str: "Display whole thread leading to , reference URLs for each" }; -fn view_tr(line: String, mut tweeter: &mut tw::TwitterCache, queryer: &mut Queryer) { +fn view_tr(line: String, mut tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, display_info: &mut DisplayInfo) { let mut thread: Vec = Vec::new(); let maybe_curr_id = TweetId::parse(line); match maybe_curr_id { Ok(curr_id) => { - let first_twete = tweeter.fetch_tweet(&curr_id, queryer).map(|x| x.to_owned()); + let first_twete = tweeter.fetch_tweet(&curr_id, queryer, display_info).map(|x| x.to_owned()); if first_twete.is_some() { thread.push(curr_id); } let mut maybe_next_id = first_twete.and_then(|x| x.reply_to_tweet.to_owned()); while let Some(next_id) = maybe_next_id { let curr_id = TweetId::Twitter(next_id); - maybe_next_id = tweeter.fetch_tweet(&curr_id, queryer).and_then(|x| x.reply_to_tweet.to_owned()); + maybe_next_id = tweeter.fetch_tweet(&curr_id, queryer, display_info).and_then(|x| x.reply_to_tweet.to_owned()); thread.push(curr_id); } }, Err(e) => { - tweeter.display_info.status(format!("Invalid id {:?}", e)); + display_info.status(format!("Invalid id {:?}", e)); } } - tweeter.display_info.recv(display::Infos::Thread(thread)); + display_info.recv(display::Infos::Thread(thread)); } pub static VIEW_THREAD_FORWARD: Command = Command { @@ -73,7 +74,7 @@ pub static VIEW_THREAD_FORWARD: Command = Command { help_str: "help me make this work" }; -fn view_tr_forward(_line: String, _tweeter: &mut tw::TwitterCache, _queryer: &mut Queryer) { +fn view_tr_forward(_line: String, _tweeter: &mut tw::TwitterCache, _queryer: &mut Queryer, display_info: &mut DisplayInfo) { // first see if we have a thread for the tweet named // if we do not, we'll have to mimic a request like // curl 'https://twitter.com/jojonila/status/914383908090691584' \ diff --git a/src/display/mod.rs b/src/display/mod.rs index 88722cc..35efa33 100644 --- a/src/display/mod.rs +++ b/src/display/mod.rs @@ -30,6 +30,7 @@ pub enum Infos { } const COMPOSE_HEIGHT: u16 = 5; + pub struct DisplayInfo { pub log_height: u16, pub prompt_height: u16, @@ -88,17 +89,17 @@ fn into_display_lines(x: Vec, width: u16) -> Vec { wrapped } -pub fn paint(tweeter: &mut ::tw::TwitterCache) -> Result<(), std::io::Error> { +pub fn paint(tweeter: &::tw::TwitterCache, display_info: &mut DisplayInfo) -> Result<(), std::io::Error> { match termion::terminal_size() { Ok((width, height)) => { // draw input prompt let mut i = 0; let log_size = 4; - let last_elem = tweeter.display_info.log.len().saturating_sub(log_size); + let last_elem = display_info.log.len().saturating_sub(log_size); { - let to_show = tweeter.display_info.log[last_elem..].iter().rev(); + let to_show = display_info.log[last_elem..].iter().rev(); for line in to_show { - print!("{}{}{}/{}: {}", cursor::Goto(1, height - i), clear::CurrentLine, tweeter.display_info.log.len() - 1 - i as usize, tweeter.display_info.log.len() - 1, line); + print!("{}{}{}/{}: {}", cursor::Goto(1, height - i), clear::CurrentLine, display_info.log.len() - 1 - i as usize, display_info.log.len() - 1, line); i = i + 1; } } @@ -108,22 +109,22 @@ pub fn paint(tweeter: &mut ::tw::TwitterCache) -> Result<(), std::io::Error> { } // draw status lines // draw tweets - let last_tail_twevent = tweeter.display_info.infos.len().saturating_sub(tweeter.display_info.infos_seek as usize); + let last_tail_twevent = display_info.infos.len().saturating_sub(display_info.infos_seek as usize); let first_tail_twevent = last_tail_twevent.saturating_sub(height as usize - 4); - let last_few_twevent: Vec = tweeter.display_info.infos[first_tail_twevent..last_tail_twevent].iter().map(|x| x.clone()).rev().collect::>(); + let last_few_twevent: Vec = display_info.infos[first_tail_twevent..last_tail_twevent].iter().map(|x| x.clone()).rev().collect::>(); - let mut h = tweeter.display_info.ui_height(); + let mut h = display_info.ui_height(); /* * draw in whatever based on mode... */ - let (cursor_x, cursor_y) = match tweeter.display_info.mode.clone() { + let (cursor_x, cursor_y) = match display_info.mode.clone() { None => { let handle = tweeter.current_profile().map(|profile| profile.user.handle.to_owned()).unwrap_or("_default_".to_owned()); print!("{}{}", cursor::Goto(1, height - 6), clear::CurrentLine); - print!("{}{}@{}>{}", cursor::Goto(1, height - 5), clear::CurrentLine, handle, tweeter.display_info.input_buf.clone().into_iter().collect::()); + print!("{}{}@{}>{}", cursor::Goto(1, height - 5), clear::CurrentLine, handle, display_info.input_buf.clone().into_iter().collect::()); print!("{}{}", cursor::Goto(1, height - 4), clear::CurrentLine); - ((1 + handle.len() + 2 + tweeter.display_info.input_buf.len()) as u16, height as u16 - 5) + ((1 + handle.len() + 2 + display_info.input_buf.len()) as u16, height as u16 - 5) } Some(DisplayMode::Compose(x)) => { let mut lines: Vec = vec![]; @@ -148,7 +149,7 @@ pub fn paint(tweeter: &mut ::tw::TwitterCache) -> Result<(), std::io::Error> { (cursor_idx as u16 + 3, height as u16 - 5) // TODO: panic on underflow } Some(DisplayMode::Reply(twid, msg)) => { - let mut lines = render_twete(&twid, tweeter, Some(width)); + let mut lines = render_twete(&twid, tweeter, display_info, Some(width)); lines.push(" -------- ".to_owned()); let msg_lines = into_display_lines(msg.split("\n").map(|x| x.to_owned()).collect(), width - 2); let cursor_idx = msg_lines.last().map(|x| x.len()).unwrap_or(0); @@ -179,7 +180,7 @@ pub fn paint(tweeter: &mut ::tw::TwitterCache) -> Result<(), std::io::Error> { wrapped.into_iter().rev().collect() } Infos::Tweet(id) => { - let pre_split: Vec = render_twete(&id, tweeter, Some(width)); + let pre_split: Vec = render_twete(&id, tweeter, display_info, Some(width)); let total_length: usize = pre_split.iter().map(|x| x.len()).sum(); let wrapped = if total_length <= 1024 { into_display_lines(pre_split, width) @@ -189,14 +190,14 @@ pub fn paint(tweeter: &mut ::tw::TwitterCache) -> Result<(), std::io::Error> { wrapped.into_iter().rev().collect() } Infos::TweetWithContext(id, context) => { - let mut lines = render_twete(&id, tweeter, Some(width)).iter().map(|x| x.to_owned()).rev().collect::>(); + let mut lines = render_twete(&id, tweeter, display_info, Some(width)).iter().map(|x| x.to_owned()).rev().collect::>(); lines.push(context); lines } Infos::Thread(ids) => { // TODO: group together thread elements by the same person a little // better.. - let mut tweets: Vec> = ids.iter().rev().map(|x| render_twete(x, tweeter, Some(width))).collect(); + let mut tweets: Vec> = ids.iter().rev().map(|x| render_twete(x, tweeter, display_info, Some(width))).collect(); let last = tweets.pop(); let mut lines = tweets.into_iter().fold(Vec::new(), |mut sum, lines| { sum.extend(lines); @@ -214,7 +215,7 @@ pub fn paint(tweeter: &mut ::tw::TwitterCache) -> Result<(), std::io::Error> { lines.into_iter().rev().collect() }, Infos::Event(e) => { - let pre_split = e.clone().render(tweeter, width); + let pre_split = e.clone().render(tweeter, display_info, width); let total_length: usize = pre_split.iter().map(|x| x.len()).sum(); let wrapped = if total_length <= 1024 { into_display_lines(pre_split, width) @@ -283,11 +284,11 @@ fn color_for(handle: &String) -> termion::color::Fg<&color::Color> { } pub trait Render { - fn render(self, tweeter: &mut ::tw::TwitterCache, width: u16) -> Vec; + fn render(self, tweeter: &::tw::TwitterCache, display_info: &mut DisplayInfo, width: u16) -> Vec; } impl Render for tw::events::Event { - fn render(self, tweeter: &mut ::tw::TwitterCache, width: u16) -> Vec { + fn render(self, tweeter: &::tw::TwitterCache, display_info: &mut DisplayInfo, width: u16) -> Vec { let mut result = Vec::new(); match self { tw::events::Event::Quoted { user_id, twete_id } => { @@ -296,13 +297,13 @@ impl Render for tw::events::Event { let user = tweeter.retrieve_user(&user_id).unwrap(); result.push(format!(" quoted_tweet : {} (@{})", user.name, user.handle)); } - render_twete(&TweetId::Twitter(twete_id), tweeter, Some(width)); + render_twete(&TweetId::Twitter(twete_id), tweeter, display_info, Some(width)); } tw::events::Event::Deleted { user_id, twete_id } => { if let Some(handle) = tweeter.retrieve_user(&user_id).map(|x| &x.handle).map(|x| x.clone()) { - if let Some(_tweet) = tweeter.retrieve_tweet(&TweetId::Twitter(twete_id.to_owned())).map(|x| x.clone()) { + if let Some(_tweet) = tweeter.retrieve_tweet(&TweetId::Twitter(twete_id.to_owned()), display_info).map(|x| x.clone()) { result.push(format!("-------------DELETED------------------")); - result.extend(render_twete(&TweetId::Twitter(twete_id), tweeter, Some(width))); + result.extend(render_twete(&TweetId::Twitter(twete_id), tweeter, display_info, Some(width))); result.push(format!("-------------DELETED------------------")); } else { result.push(format!("dunno what, but do know who: {} - {}", user_id, handle)); @@ -317,7 +318,7 @@ impl Render for tw::events::Event { let user = tweeter.retrieve_user(&user_id).unwrap(); result.push(format!(" +rt_rt : {} (@{})", user.name, user.handle)); } - result.extend(render_twete(&TweetId::Twitter(twete_id), tweeter, Some(width))); + result.extend(render_twete(&TweetId::Twitter(twete_id), tweeter, display_info, Some(width))); }, tw::events::Event::Fav_RT { user_id, twete_id } => { result.push("---------------------------------".to_string()); @@ -326,7 +327,7 @@ impl Render for tw::events::Event { } else { result.push(format!(" +rt_fav but don't know who {} is", user_id)); } - result.extend(render_twete(&TweetId::Twitter(twete_id), tweeter, Some(width))); + result.extend(render_twete(&TweetId::Twitter(twete_id), tweeter, display_info, Some(width))); }, tw::events::Event::Fav { user_id, twete_id } => { result.push("---------------------------------".to_string()); @@ -334,7 +335,7 @@ impl Render for tw::events::Event { let user = tweeter.retrieve_user(&user_id).unwrap(); result.push(format!("{} +fav : {} (@{}){}", color::Fg(color::Yellow), user.name, user.handle, color::Fg(color::Reset))); } - result.extend(render_twete(&TweetId::Twitter(twete_id), tweeter, Some(width))); + result.extend(render_twete(&TweetId::Twitter(twete_id), tweeter, display_info, Some(width))); }, tw::events::Event::Unfav { user_id, twete_id } => { result.push("---------------------------------".to_string()); @@ -342,7 +343,7 @@ impl Render for tw::events::Event { let user = tweeter.retrieve_user(&user_id).unwrap(); result.push(format!("{} -fav : {} (@{}){}", color::Fg(color::Yellow), user.name, user.handle, color::Fg(color::Reset))); } - result.extend(render_twete(&TweetId::Twitter(twete_id), tweeter, Some(width))); + result.extend(render_twete(&TweetId::Twitter(twete_id), tweeter, display_info, Some(width))); }, tw::events::Event::Followed { user_id } => { result.push("---------------------------------".to_string()); @@ -368,12 +369,12 @@ fn pad_lines(lines: Vec, padding: &str) -> Vec { lines.into_iter().map(|x| format!("{}{}", padding, x)).collect() } -pub fn render_twete(twete_id: &TweetId, tweeter: &mut tw::TwitterCache, width: Option) -> Vec { - let mut lines = render_twete_no_recurse(twete_id, tweeter, width); - match tweeter.retrieve_tweet(twete_id).map(|x| x.clone()) { +pub fn render_twete(twete_id: &TweetId, tweeter: &tw::TwitterCache, display_info: &mut DisplayInfo, width: Option) -> Vec { + let mut lines = render_twete_no_recurse(twete_id, tweeter, display_info, width); + match tweeter.retrieve_tweet(twete_id, display_info).map(|x| x.clone()) { Some(twete) => { if let Some(ref qt_id) = twete.quoted_tweet_id { - lines.extend(pad_lines(render_twete_no_recurse(&TweetId::Twitter(qt_id.to_owned()), tweeter, width.map(|x| x - 4)), " ")); + lines.extend(pad_lines(render_twete_no_recurse(&TweetId::Twitter(qt_id.to_owned()), tweeter, display_info, width.map(|x| x - 4)), " ")); } }, None => { /* awkward */ } @@ -381,11 +382,11 @@ pub fn render_twete(twete_id: &TweetId, tweeter: &mut tw::TwitterCache, width: O lines } -pub fn render_twete_no_recurse(twete_id: &TweetId, tweeter: &mut tw::TwitterCache, width: Option) -> Vec { +pub fn render_twete_no_recurse(twete_id: &TweetId, tweeter: &tw::TwitterCache, display_info: &mut DisplayInfo, width: Option) -> Vec { // ~~ reactive ~~ layout if the terminal isn't wide enough? for now just wrap to passed width let mut result = Vec::new(); let id_color = color::Fg(color::Rgb(180, 80, 40)); - match tweeter.retrieve_tweet(twete_id).map(|x| x.clone()) { + match tweeter.retrieve_tweet(twete_id, display_info).map(|x| x.clone()) { Some(twete) => { // if we got the tweet, the API gave us the user too let user = tweeter.retrieve_user(&twete.author_id).map(|x| x.clone()).unwrap(); @@ -406,7 +407,7 @@ pub fn render_twete_no_recurse(twete_id: &TweetId, tweeter: &mut tw::TwitterCach .clone() .map(|rt_id| (TweetId::Twitter(rt_id), Some(TweetId::Twitter(twete.id.to_owned())))).unwrap_or((TweetId::Twitter(twete.id.to_owned()), None)); // retrieve_* taking mut tweeter REALLY messes stuff up. - let tweet = tweeter.retrieve_tweet(&tweet_id).unwrap().clone(); + let tweet = tweeter.retrieve_tweet(&tweet_id, display_info).unwrap().clone(); let tweet_author = tweeter.retrieve_user(&tweet.author_id).unwrap().clone(); // now we've unfurled it so id is the original tweet either way, maybe_rt_id is the id @@ -416,7 +417,7 @@ pub fn render_twete_no_recurse(twete_id: &TweetId, tweeter: &mut tw::TwitterCach let mut author_string = format!("{}{}{} ({}@{}{})", color_for(&tweet_author.handle), tweet_author.name, color::Fg(color::Reset), color_for(&tweet_author.handle), tweet_author.handle, color::Fg(color::Reset)); if let Some(reply_id) = tweet.reply_to_tweet.clone() { - let reply_tweet_id = match tweeter.retrieve_tweet(&TweetId::Twitter(reply_id.to_owned())) { + let reply_tweet_id = match tweeter.retrieve_tweet(&TweetId::Twitter(reply_id.to_owned()), display_info) { Some(reply_tweet) => TweetId::Bare(reply_tweet.internal_id), None => TweetId::Twitter(reply_id) }; @@ -424,7 +425,7 @@ pub fn render_twete_no_recurse(twete_id: &TweetId, tweeter: &mut tw::TwitterCach } if let Some(rt_id) = maybe_rt_id { - let rt = tweeter.retrieve_tweet(&rt_id).unwrap().clone(); + let rt = tweeter.retrieve_tweet(&rt_id, display_info).unwrap().clone(); let rt_author = tweeter.retrieve_user(&rt.author_id).unwrap().clone(); id_string.push_str(&format!(" (rt id {})", rt.internal_id)); author_string.push_str(&format!(" via {}{}{} ({}@{}{}) RT", color_for(&rt_author.handle), rt_author.name, color::Fg(color::Reset), color_for(&rt_author.handle), rt_author.handle, color::Fg(color::Reset))); diff --git a/src/main.rs b/src/main.rs index e45a799..73ad9d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -206,9 +206,11 @@ fn main() { // even though it's not ever present before here println!("Loading cache..."); - let mut tweeter = tw::TwitterCache::load_cache(); + let mut display_info = display::DisplayInfo::default(); - tweeter.display_info.status("Cache loaded".to_owned()); + let mut tweeter = tw::TwitterCache::load_cache(&mut display_info); + + display_info.status("Cache loaded".to_owned()); let (twete_tx, twete_rx) = chan::sync::<(u8, Vec)>(0); let (coordination_tx, coordination_rx) = chan::sync::<(u8, TwitterConnectionState)>(0); @@ -244,73 +246,73 @@ fn main() { tcsetattr(0, TCSANOW, &new_termios).unwrap(); - match display::paint(&mut tweeter) { + match display::paint(&mut tweeter, &mut display_info) { Ok(_) => (), Err(e) => println!("{}", e) // TODO: we got here because writing to stdout failed. what to do now? }; - do_ui(ui_rx, twete_rx, &twete_tx, coordination_rx, &coordination_tx, &mut tweeter, &mut queryer); + do_ui(ui_rx, twete_rx, &twete_tx, coordination_rx, &coordination_tx, &mut tweeter, &mut display_info, &mut queryer); tcsetattr(0, TCSANOW, &termios); } -fn handle_input(event: termion::event::Event, tweeter: &mut tw::TwitterCache, queryer: &mut ::Queryer) { +fn handle_input(event: termion::event::Event, tweeter: &mut tw::TwitterCache, queryer: &mut ::Queryer, display_info: &mut display::DisplayInfo) { match event { Event::Key(Key::Backspace) => { - match tweeter.display_info.mode.clone() { - None => { tweeter.display_info.input_buf.pop(); }, + match display_info.mode.clone() { + None => { display_info.input_buf.pop(); }, Some(display::DisplayMode::Compose(msg)) => { let mut newstr = msg.clone(); newstr.pop(); - tweeter.display_info.mode = Some(display::DisplayMode::Compose(newstr)); + display_info.mode = Some(display::DisplayMode::Compose(newstr)); }, Some(display::DisplayMode::Reply(twid, msg)) => { let mut newstr = msg.clone(); newstr.pop(); - tweeter.display_info.mode = Some(display::DisplayMode::Reply(twid, newstr)); + display_info.mode = Some(display::DisplayMode::Reply(twid, newstr)); } } } // would Shift('\n') but.. that doesn't exist. // would Ctrl('\n') but.. that doesn't work. Event::Key(Key::Ctrl('u')) => { - match tweeter.display_info.mode.clone() { - None => tweeter.display_info.input_buf = vec![], + match display_info.mode.clone() { + None => display_info.input_buf = vec![], Some(display::DisplayMode::Compose(msg)) => { // TODO: clear only one line? - tweeter.display_info.mode = Some(display::DisplayMode::Compose("".to_owned())); + display_info.mode = Some(display::DisplayMode::Compose("".to_owned())); } Some(display::DisplayMode::Reply(twid, msg)) => { - tweeter.display_info.mode = Some(display::DisplayMode::Reply(twid, "".to_owned())); + display_info.mode = Some(display::DisplayMode::Reply(twid, "".to_owned())); } } } Event::Key(Key::Ctrl('n')) => { - match tweeter.display_info.mode.clone() { + match display_info.mode.clone() { Some(display::DisplayMode::Compose(msg)) => { - tweeter.display_info.mode = Some(display::DisplayMode::Compose(format!("{}{}", msg, "\n"))); + display_info.mode = Some(display::DisplayMode::Compose(format!("{}{}", msg, "\n"))); } _ => {} } } // TODO: ctrl+u, ctrl+w Event::Key(Key::Char(x)) => { - match tweeter.display_info.mode.clone() { + match display_info.mode.clone() { None => { if x == '\n' { - let line = tweeter.display_info.input_buf.drain(..).collect::(); - tweeter.handle_user_input(line.into_bytes(), queryer); + let line = display_info.input_buf.drain(..).collect::(); + tweeter.handle_user_input(line.into_bytes(), queryer, display_info); } else { - tweeter.display_info.input_buf.push(x); + display_info.input_buf.push(x); } } Some(display::DisplayMode::Compose(msg)) => { if x == '\n' { // TODO: move this somewhere better. - ::commands::twete::send_twete(msg, tweeter, queryer); - tweeter.display_info.mode = None; + ::commands::twete::send_twete(msg, tweeter, queryer, display_info); + display_info.mode = None; } else { - tweeter.display_info.mode = Some(display::DisplayMode::Compose(format!("{}{}", msg, x))); + display_info.mode = Some(display::DisplayMode::Compose(format!("{}{}", msg, x))); } } Some(display::DisplayMode::Reply(twid, msg)) => { @@ -318,30 +320,30 @@ fn handle_input(event: termion::event::Event, tweeter: &mut tw::TwitterCache, qu match tweeter.current_profile().map(|profile| profile.to_owned()) { Some(profile) => { // TODO: move this somewhere better. - ::commands::twete::send_reply(msg, twid, tweeter, queryer, profile.creds); + ::commands::twete::send_reply(msg, twid, tweeter, queryer, profile.creds, display_info); }, None => { - tweeter.display_info.status("Cannot reply when not logged in".to_owned()); + display_info.status("Cannot reply when not logged in".to_owned()); } } - tweeter.display_info.mode = None; + display_info.mode = None; } else { - tweeter.display_info.mode = Some(display::DisplayMode::Reply(twid, format!("{}{}", msg, x))); + display_info.mode = Some(display::DisplayMode::Reply(twid, format!("{}{}", msg, x))); } } } }, Event::Key(Key::End) => { - tweeter.display_info.infos_seek = 0; + display_info.infos_seek = 0; } Event::Key(Key::PageUp) => { - tweeter.display_info.infos_seek = tweeter.display_info.infos_seek.saturating_add(1); + display_info.infos_seek = display_info.infos_seek.saturating_add(1); } Event::Key(Key::PageDown) => { - tweeter.display_info.infos_seek = tweeter.display_info.infos_seek.saturating_sub(1); + display_info.infos_seek = display_info.infos_seek.saturating_sub(1); } Event::Key(Key::Esc) => { - tweeter.display_info.mode = None; + display_info.mode = None; } Event::Key(_) => { } Event::Mouse(_) => { } @@ -349,18 +351,18 @@ fn handle_input(event: termion::event::Event, tweeter: &mut tw::TwitterCache, qu } } -fn handle_twitter_line(conn_id: u8, line: Vec, mut tweeter: &mut tw::TwitterCache, mut queryer: &mut ::Queryer) { +fn handle_twitter_line(conn_id: u8, line: Vec, mut tweeter: &mut tw::TwitterCache, mut queryer: &mut ::Queryer, display_info: &mut display::DisplayInfo) { let jsonstr = std::str::from_utf8(&line).unwrap().trim(); /* TODO: replace from_str with from_slice? */ match serde_json::from_str(&jsonstr) { Ok(json) => { - tw::handle_message(conn_id, json, &mut tweeter, &mut queryer); + tw::handle_message(conn_id, json, &mut tweeter, display_info, &mut queryer); if tweeter.needs_save && tweeter.caching_permitted { - tweeter.store_cache(); + tweeter.store_cache(display_info); } }, Err(e) => - tweeter.display_info.status(format!("Error reading twitter line: {}", jsonstr)) + display_info.status(format!("Error reading twitter line: {}", jsonstr)) } } @@ -371,6 +373,7 @@ fn do_ui( coordination_rx: chan::Receiver<(u8, TwitterConnectionState)>, coordination_tx: &chan::Sender<(u8, TwitterConnectionState)>, mut tweeter: &mut tw::TwitterCache, + mut display_info: &mut display::DisplayInfo, mut queryer: &mut ::Queryer ) { loop { @@ -383,7 +386,7 @@ fn do_ui( tweeter.connection_map.insert(conn_id, profile_name); }, TwitterConnectionState::Connected => { - tweeter.display_info.status(format!("Stream connected for profile \"{}\"", tweeter.connection_map[&conn_id])); + display_info.status(format!("Stream connected for profile \"{}\"", tweeter.connection_map[&conn_id])); }, TwitterConnectionState::Closed => { tweeter.connection_map.remove(&conn_id); @@ -394,22 +397,22 @@ fn do_ui( } }, twete_rx.recv() -> twete => match twete { - Some((conn_id, line)) => handle_twitter_line(conn_id, line, tweeter, queryer), + Some((conn_id, line)) => handle_twitter_line(conn_id, line, tweeter, queryer, display_info), None => { - tweeter.display_info.status("Twitter stream hung up...".to_owned()); - display::paint(tweeter).unwrap(); + display_info.status("Twitter stream hung up...".to_owned()); + display::paint(tweeter, display_info).unwrap(); return; // if the twitter channel died, something real bad happeneed? } }, ui_rx.recv() -> user_input => match user_input { - Some(Ok(event)) => handle_input(event, tweeter, queryer), + Some(Ok(event)) => handle_input(event, tweeter, queryer, display_info), Some(Err(_)) => (), /* stdin closed? */ None => return // UI ded } } // one day display_info should be distinct - match display::paint(tweeter) { + match display::paint(tweeter, display_info) { Ok(_) => (), Err(e) => println!("{}", e) // TODO: we got here because writing to stdout failed. what to do now? }; @@ -438,8 +441,8 @@ fn do_ui( for command in commands::COMMANDS { help_lines.push(format!("{}{: { @@ -449,16 +452,16 @@ fn do_ui( connect_twitter_stream(tweeter.app_key.clone(), profile_name, user_creds, twete_tx.clone(), coordination_tx.clone(), get_id()) }, None => { - tweeter.display_info.status(format!("No profile named {}", profile_name)); + display_info.status(format!("No profile named {}", profile_name)); } } }, tw::AppState::Shutdown => { - tweeter.display_info.status("Saving cache...".to_owned()); - display::paint(tweeter).unwrap(); - tweeter.store_cache(); - tweeter.display_info.status("Bye bye!".to_owned()); - display::paint(tweeter).unwrap(); + display_info.status("Saving cache...".to_owned()); + display::paint(tweeter, display_info).unwrap(); + tweeter.store_cache(display_info); + display_info.status("Bye bye!".to_owned()); + display::paint(tweeter, display_info).unwrap(); return; }, tw::AppState::View | tw::AppState::Compose => { /* nothing special to do */ } diff --git a/src/tw/mod.rs b/src/tw/mod.rs index 3d3f08a..ee3b73e 100644 --- a/src/tw/mod.rs +++ b/src/tw/mod.rs @@ -23,6 +23,8 @@ use self::tweet::Tweet; pub mod user; use self::user::User; +use display::DisplayInfo; + #[derive(Clone)] pub enum AppState { Shutdown, @@ -108,8 +110,8 @@ pub struct TwitterCache { pub caching_permitted: bool, #[serde(skip)] id_conversions: IdConversions, - #[serde(skip)] - pub display_info: display::DisplayInfo, +// #[serde(skip)] +// pub display_info: display::DisplayInfo, #[serde(skip)] pub state: AppState, #[serde(skip)] @@ -226,10 +228,7 @@ impl IdConversions { // // except in the TweetId::Twitter case we TweetId -> Option -> Option ... to -> // Option in the future? - // // WHY must we take mutable borrow of TwitterCache here, you ask? - // // well, because it contains display_info, and retrieve_tweet can - // // end up logging, for now! - fn to_inner_id(&self, tweeter: &mut TwitterCache, twid: TweetId) -> Option { + fn to_inner_id(&self, tweeter: &TwitterCache, twid: TweetId, display_info: &mut DisplayInfo) -> Option { match twid { TweetId::Today(num) => { let first_for_today: u64 = 0; @@ -240,7 +239,7 @@ impl IdConversions { Some(first_for_date + num) }, TweetId::Bare(num) => Some(num), - twid @ TweetId::Twitter(_) => tweeter.retrieve_tweet(&twid).map(|x| x.internal_id) + twid @ TweetId::Twitter(_) => tweeter.retrieve_tweet(&twid, display_info).map(|x| x.internal_id) } } } @@ -405,7 +404,6 @@ impl TwitterCache { caching_permitted: true, threads: HashMap::new(), id_conversions: IdConversions::default(), - display_info: display::DisplayInfo::default(), state: AppState::View, connection_map: HashMap::new() } @@ -428,13 +426,13 @@ impl TwitterCache { // TODO: pull out the "Cache" part of TwitterCache, it can be serialized/deserialized - the // rest of the history is just for the running instance.. - pub fn handle_user_input(&mut self, line: Vec, mut queryer: &mut Queryer) { + pub fn handle_user_input(&mut self, line: Vec, mut queryer: &mut Queryer, display_info: &mut DisplayInfo) { let command_bare = String::from_utf8(line).unwrap(); let command = command_bare.trim(); if let Some((line, cmd)) = parse_word_command(&command, ::commands::COMMANDS) { - (cmd.exec)(line.to_owned(), self, &mut queryer); + (cmd.exec)(line.to_owned(), self, &mut queryer, display_info); } else { - self.display_info.status(format!("I don't know what {} means", command).to_string()); + display_info.status(format!("I don't know what {} means", command).to_string()); } } @@ -443,10 +441,10 @@ impl TwitterCache { cache.caching_permitted = false; cache } - pub fn add_profile(&mut self, profile: TwitterProfile, name: Option) { + pub fn add_profile(&mut self, profile: TwitterProfile, name: Option, display_info: &mut DisplayInfo) { self.profiles.insert(name.unwrap_or(profile.user.handle.to_owned()), profile); if self.caching_permitted { - self.store_cache(); + self.store_cache(display_info); } } fn cache_user(&mut self, user: User) { @@ -479,7 +477,7 @@ impl TwitterCache { self.number_and_insert_tweet(tweet); } } - pub fn store_cache(&mut self) { + pub fn store_cache(&mut self, display_info: &mut DisplayInfo) { if self.caching_permitted { if Path::new(TwitterCache::PROFILE_DIR).is_dir() { let profile = OpenOptions::new() @@ -491,7 +489,7 @@ impl TwitterCache { .unwrap(); serde_json::to_writer(profile, self).unwrap(); } else { - self.display_info.status("No cache dir exists...".to_owned()); + display_info.status("No cache dir exists...".to_owned()); } } } @@ -504,7 +502,7 @@ impl TwitterCache { } } } - pub fn load_cache() -> TwitterCache { + pub fn load_cache(display_info: &mut DisplayInfo) -> TwitterCache { if Path::new(TwitterCache::PROFILE_CACHE).is_file() { let mut buf = vec![]; let mut profile = File::open(TwitterCache::PROFILE_CACHE).unwrap(); @@ -537,20 +535,20 @@ impl TwitterCache { Err(e) => { // TODO! should be able to un-frick profile after startup. let mut cache = TwitterCache::new_without_caching(); - cache.display_info.status(format!("Error reading profile, profile caching disabled... {}", e)); + display_info.status(format!("Error reading profile, profile caching disabled... {}", e)); cache } } } Err(e) => { let mut cache = TwitterCache::new_without_caching(); - cache.display_info.status(format!("Error reading cached profile: {}. Profile caching disabled.", e)); + display_info.status(format!("Error reading cached profile: {}. Profile caching disabled.", e)); cache } } } else { let mut cache = TwitterCache::new(); - cache.display_info.status(format!("Hello! First time setup?")); + display_info.status(format!("Hello! First time setup?")); cache } } @@ -581,7 +579,7 @@ impl TwitterCache { self.cache_user(user); } } - pub fn cache_api_event(&mut self, conn_id: u8, json: serde_json::Map, mut queryer: &mut ::Queryer) { + pub fn cache_api_event(&mut self, conn_id: u8, json: serde_json::Map, mut queryer: &mut ::Queryer, display_info: &mut DisplayInfo) { /* don't really care to hold on to who fav, unfav, ... when, just pick targets out. */ match json.get("event").and_then(|x| x.as_str()) { Some("quoted_tweet") => { @@ -610,7 +608,7 @@ impl TwitterCache { }, Some("delete") => { let user_id = json["delete"]["status"]["user_id_str"].as_str().unwrap().to_string(); - self.fetch_user(&user_id, &mut queryer); + self.fetch_user(&user_id, &mut queryer, display_info); }, Some("follow") => { let follower = json["source"]["id_str"].as_str().unwrap().to_string(); @@ -641,7 +639,7 @@ impl TwitterCache { /* nothing else to care about now, i think? */ } } - pub fn retrieve_tweet(&mut self, tweet_id: &TweetId) -> Option<&Tweet> { + pub fn retrieve_tweet(&self, tweet_id: &TweetId, display_info: &mut DisplayInfo) -> Option<&Tweet> { match tweet_id { &TweetId::Bare(ref id) => { let maybe_tweet_id = self.id_conversions.id_to_tweet_id.get(id); @@ -652,11 +650,11 @@ impl TwitterCache { }, &TweetId::Today(ref id) => { let inner_id = self.id_conversions.id_to_tweet_id.get(id); - self.display_info.status("Retrieving tweets with dated IDs is not yet supported.".to_string()); + display_info.status("Retrieving tweets with dated IDs is not yet supported.".to_string()); None }, &TweetId::Dated(ref date, ref id) => { - self.display_info.status("Retrieving tweets with dated IDs is not yet supported.".to_string()); + display_info.status("Retrieving tweets with dated IDs is not yet supported.".to_string()); None }, &TweetId::Twitter(ref id) => self.tweets.get(id) @@ -665,37 +663,37 @@ impl TwitterCache { pub fn retrieve_user(&self, user_id: &String) -> Option<&User> { self.users.get(user_id) } - pub fn fetch_tweet(&mut self, tweet_id: &TweetId, mut queryer: &mut ::Queryer) -> Option<&Tweet> { + pub fn fetch_tweet(&mut self, tweet_id: &TweetId, mut queryer: &mut ::Queryer, display_info: &mut DisplayInfo) -> Option<&Tweet> { match tweet_id { &TweetId::Bare(ref id) => { // we can do nothing but just try to get it - self.retrieve_tweet(tweet_id) + self.retrieve_tweet(tweet_id, display_info) } &TweetId::Today(ref id) => { // we can do nothing but just try to get it - self.retrieve_tweet(tweet_id) + self.retrieve_tweet(tweet_id, display_info) }, &TweetId::Dated(ref date, ref id) => { // we can do nothing but just try to get it - self.retrieve_tweet(tweet_id) + self.retrieve_tweet(tweet_id, display_info) }, &TweetId::Twitter(ref id) => { if !self.tweets.contains_key(id) { match self.look_up_tweet(id, &mut queryer) { Ok(json) => self.cache_api_tweet(json), - Err(e) => self.display_info.status(format!("Unable to retrieve tweet {}:\n{}", id, e)) + Err(e) => display_info.status(format!("Unable to retrieve tweet {}:\n{}", id, e)) }; } - self.retrieve_tweet(tweet_id) + self.retrieve_tweet(tweet_id, display_info) } } } - pub fn fetch_user(&mut self, user_id: &String, mut queryer: &mut ::Queryer) -> Option<&User> { + pub fn fetch_user(&mut self, user_id: &String, mut queryer: &mut ::Queryer, display_info: &mut DisplayInfo) -> Option<&User> { if !self.users.contains_key(user_id) { let maybe_parsed = self.look_up_user(user_id, &mut queryer).and_then(|x| User::from_json(x)); match maybe_parsed { Ok(tw) => self.cache_user(tw), - Err(e) => self.display_info.status(format!("Unable to retrieve user {}:\n{}", user_id, e)) + Err(e) => display_info.status(format!("Unable to retrieve user {}:\n{}", user_id, e)) } } self.users.get(user_id) @@ -750,14 +748,15 @@ fn handle_twitter_event( conn_id: u8, structure: serde_json::Map, tweeter: &mut TwitterCache, - mut queryer: &mut ::Queryer) { - tweeter.cache_api_event(conn_id, structure.clone(), &mut queryer); + display_info: &mut DisplayInfo, + queryer: &mut ::Queryer) { + tweeter.cache_api_event(conn_id, structure.clone(), queryer, display_info); match events::Event::from_json(structure) { Ok(event) => { - tweeter.display_info.recv(display::Infos::Event(event)); + display_info.recv(display::Infos::Event(event)); }, Err(e) => { - tweeter.display_info.status(format!("Unknown twitter json: {:?}", e)); + display_info.status(format!("Unknown twitter json: {:?}", e)); } } } @@ -766,9 +765,10 @@ fn handle_twitter_delete( conn_id: u8, structure: serde_json::Map, tweeter: &mut TwitterCache, + display_info: &mut DisplayInfo, _queryer: &mut ::Queryer) { /* - tweeter.display_info.recv(display::Infos::Event( + display_info.recv(display::Infos::Event( events::Event::Deleted { user_id: structure["delete"]["status"]["user_id_str"].as_str().unwrap().to_string(), twete_id: structure["delete"]["status"]["id_str"].as_str().unwrap().to_string() @@ -781,10 +781,11 @@ fn handle_twitter_twete( conn_id: u8, structure: serde_json::Map, tweeter: &mut TwitterCache, + display_info: &mut DisplayInfo, _queryer: &mut ::Queryer) { let twete_id = structure["id_str"].as_str().unwrap().to_string(); tweeter.cache_api_tweet(serde_json::Value::Object(structure)); - tweeter.display_info.recv(display::Infos::Tweet(TweetId::Twitter(twete_id))); + display_info.recv(display::Infos::Tweet(TweetId::Twitter(twete_id))); // display::render_twete(&twete_id, tweeter); } @@ -792,15 +793,17 @@ fn handle_twitter_dm( conn_id: u8, structure: serde_json::Map, tweeter: &mut TwitterCache, + display_info: &mut DisplayInfo, _queryer: &mut ::Queryer) { // show DM - tweeter.display_info.recv(display::Infos::DM(structure["direct_message"]["text"].as_str().unwrap().to_string())); + display_info.recv(display::Infos::DM(structure["direct_message"]["text"].as_str().unwrap().to_string())); } fn handle_twitter_welcome( conn_id: u8, structure: serde_json::Map, tweeter: &mut TwitterCache, + display_info: &mut DisplayInfo, queryer: &mut ::Queryer) { let app_key = tweeter.app_key.clone(); let followers_changes = { @@ -823,20 +826,20 @@ fn handle_twitter_welcome( match followers_changes { Ok((my_name, new_following, lost_following, (new_followers, lost_followers))) => { for user in new_following { - tweeter.display_info.status(format!("New following! {}", user)); + display_info.status(format!("New following! {}", user)); } for user in lost_following { - tweeter.display_info.status(format!("Not following {} anymore", user)); + display_info.status(format!("Not following {} anymore", user)); } for user in new_followers { - tweeter.display_info.status(format!("New follower! {}", user)); + display_info.status(format!("New follower! {}", user)); } for user in lost_followers { - tweeter.display_info.status(format!("{} isn't following anymore", user)); + display_info.status(format!("{} isn't following anymore", user)); } }, Err(e) => { - tweeter.display_info.status(e); + display_info.status(e); } } } @@ -845,22 +848,23 @@ pub fn handle_message( conn_id: u8, twete: serde_json::Value, tweeter: &mut TwitterCache, + display_info: &mut DisplayInfo, queryer: &mut ::Queryer ) { match twete { serde_json::Value::Object(objmap) => { if objmap.contains_key("event") { - handle_twitter_event(conn_id, objmap, tweeter, queryer); + handle_twitter_event(conn_id, objmap, tweeter, display_info, queryer); } else if objmap.contains_key("friends") { - handle_twitter_welcome(conn_id, objmap, tweeter, queryer); + handle_twitter_welcome(conn_id, objmap, tweeter, display_info, queryer); } else if objmap.contains_key("delete") { - handle_twitter_delete(conn_id, objmap, tweeter, queryer); + handle_twitter_delete(conn_id, objmap, tweeter, display_info, queryer); } else if objmap.contains_key("user") && objmap.contains_key("id") { - handle_twitter_twete(conn_id, objmap, tweeter, queryer); + handle_twitter_twete(conn_id, objmap, tweeter, display_info, queryer); } else if objmap.contains_key("direct_message") { - handle_twitter_dm(conn_id, objmap, tweeter, queryer); + handle_twitter_dm(conn_id, objmap, tweeter, display_info, queryer); } else { - tweeter.display_info.status(format!("Unknown json: {:?}", objmap)); + display_info.status(format!("Unknown json: {:?}", objmap)); } // self.display_info.status(""); }, -- cgit v1.1