diff options
Diffstat (limited to 'src/tw')
-rw-r--r-- | src/tw/events.rs | 10 | ||||
-rw-r--r-- | src/tw/mod.rs | 75 | ||||
-rw-r--r-- | src/tw/tweet.rs | 17 | ||||
-rw-r--r-- | src/tw/user.rs | 39 |
4 files changed, 63 insertions, 78 deletions
diff --git a/src/tw/events.rs b/src/tw/events.rs index 35167a3..0da27a1 100644 --- a/src/tw/events.rs +++ b/src/tw/events.rs @@ -22,11 +22,13 @@ impl Event { fn get_source_target_ids(structure: serde_json::Map<String, serde_json::Value>) -> Result<(String, String), String> { match ( structure.get("source").and_then(|x| x.get("id_str").and_then(|x| x.as_str())), - structure.get("target_obj").and_then(|x| x.get("id_str").and_then(|x| x.as_str())) + structure.get("target_object").and_then(|x| x.get("id_str").and_then(|x| x.as_str())) ) { (Some(source_id), Some(target_id)) => Ok((source_id.to_string(), target_id.to_string())), - (None, Some(target_id)) => Err("No id_str string at .source.id_str".to_string()), - (Some(target_id), None) => Err("No id_str string at .target_object.id_str".to_string()), + // have more particular error types for "missing fields", "missing data", "invalid + // state", etc, so downstream we can opt to investigate the bad data or not.. + (None, Some(_)) => Err("No id_str string at .source.id_str: {}".to_string()), + (Some(_), None) => Err("No id_str string at .target_object.id_str: {}".to_string()), (None, None) => Err("No id_str at source or target_object".to_string()) } } @@ -96,7 +98,7 @@ impl Event { // what about removed? // "blocked" => Blocked { }, // "unblocked" => Unblocked { }, - e => { println!("unrecognized event: {}", e); Err(e.to_string()) } + e => Err(e.to_string()) } }, None => { diff --git a/src/tw/mod.rs b/src/tw/mod.rs index d0bad59..82dfe10 100644 --- a/src/tw/mod.rs +++ b/src/tw/mod.rs @@ -15,7 +15,6 @@ use std::fs::OpenOptions; pub mod events; -use display::Render; use display; pub mod tweet; @@ -104,7 +103,7 @@ pub struct TwitterCache { #[serde(skip)] id_conversions: IdConversions, #[serde(skip)] - pub display_info: DisplayInfo + pub display_info: display::DisplayInfo } // Internally, a monotonically increasin i64 is always the id used. @@ -217,30 +216,6 @@ impl IdConversions { } } -pub struct DisplayInfo { - pub log: Vec<String>, - pub infos: Vec<display::Infos> -} - -impl Default for DisplayInfo { - fn default() -> Self { - DisplayInfo { - log: Vec::new(), - infos: Vec::new() - } - } -} - -impl DisplayInfo { - pub fn status(&mut self, stat: String) { - self.log.push(stat); - } - - pub fn recv(&mut self, info: display::Infos) { - self.infos.push(info); - } -} - use commands::Command; use Queryer; @@ -284,7 +259,7 @@ impl TwitterCache { current_user: User::default(), threads: HashMap::new(), id_conversions: IdConversions::default(), - display_info: DisplayInfo::default() + display_info: display::DisplayInfo::default() } } @@ -298,7 +273,6 @@ impl TwitterCache { } else { self.display_info.status(format!("I don't know what {} means", command).to_string()); } -// println!(""); // temporaryish because there's no visual distinction between output atm } fn new_without_caching() -> TwitterCache { @@ -332,7 +306,7 @@ impl TwitterCache { self.number_and_insert_tweet(tweet); } } - pub fn store_cache(&self) { + pub fn store_cache(&mut self) { if Path::new(TwitterCache::PROFILE_DIR).is_dir() { let profile = OpenOptions::new() .write(true) @@ -342,7 +316,7 @@ impl TwitterCache { .unwrap(); serde_json::to_writer(profile, self).unwrap(); } else { - println!("No cache dir exists..."); + self.display_info.status("No cache dir exists...".to_owned()); } // store cache } @@ -398,23 +372,29 @@ impl TwitterCache { } } pub fn cache_api_tweet(&mut self, json: serde_json::Value) { - if let Some((rt, rt_user)) = json.get("retweeted_status").and_then(|x| Tweet::from_api_json(x.to_owned())) { + // TODO: log error somehow + if let Some(Ok((rt, rt_user))) = json.get("retweeted_status").map(|x| Tweet::from_api_json(x.to_owned())) { self.cache_user(rt_user); self.cache_tweet(rt); } - if let Some((qt, qt_user)) = json.get("quoted_status").and_then(|x| Tweet::from_api_json(x.to_owned())) { + // TODO: log error somehow + if let Some(Ok((qt, qt_user))) = json.get("quoted_status").map(|x| Tweet::from_api_json(x.to_owned())) { self.cache_user(qt_user); self.cache_tweet(qt); } - if let Some((twete, user)) = Tweet::from_api_json(json) { + // TODO: log error somehow + if let Ok((twete, user)) = Tweet::from_api_json(json) { self.cache_user(user); self.cache_tweet(twete); } } pub fn cache_api_user(&mut self, json: serde_json::Value) { - if let Some(user) = User::from_json(json) { + // TODO: log error somehow + // TODO: probably means display_info needs a more technical-filled log for debugging, + // independent of the user-facing statuses, like "invalid id" + if let Ok(user) = User::from_json(json) { self.cache_user(user); } } @@ -517,8 +497,8 @@ impl TwitterCache { &TweetId::Twitter(ref id) => { if !self.tweets.contains_key(id) { match self.look_up_tweet(id, &mut queryer) { - Some(json) => self.cache_api_tweet(json), - None => self.display_info.status(format!("Unable to retrieve tweet {}", id)) + Ok(json) => self.cache_api_tweet(json), + Err(e) => self.display_info.status(format!("Unable to retrieve tweet {}:\n{}", id, e)) }; } self.retrieve_tweet(tweet_id) @@ -529,8 +509,8 @@ impl TwitterCache { 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 { - Some(tw) => self.cache_user(tw), - None => self.display_info.status(format!("Unable to retrieve user {}", user_id)) + Ok(tw) => self.cache_user(tw), + Err(e) => self.display_info.status(format!("Unable to retrieve user {}:\n{}", user_id, e)) } } self.users.get(user_id) @@ -540,13 +520,13 @@ impl TwitterCache { let new_uids = &uid_set - &self.following; for user in &new_uids { - println!("New following! {}", user); + self.display_info.status(format!("New following! {}", user)); self.add_following(user); } let lost_uids = &self.following - &uid_set; for user in &lost_uids { - println!("Bye, friend! {}", user); + self.display_info.status(format!("Bye, friend! {}", user)); self.remove_following(user); } } @@ -555,13 +535,13 @@ impl TwitterCache { let new_uids = &uid_set - &self.followers; for user in &new_uids { - println!("New follower! {}", user); + self.display_info.status(format!("New follower! {}", user)); self.add_follower(user); } let lost_uids = &self.followers - &uid_set; for user in &lost_uids { - println!("Bye, friend! {}", user); + self.display_info.status(format!("Bye, friend! {}", user)); self.remove_follower(user); } } @@ -588,21 +568,21 @@ impl TwitterCache { self.follower_history.insert(user_id.to_owned(), ("unfollow".to_string(), Utc::now().timestamp())); } - fn look_up_user(&mut self, id: &str, queryer: &mut ::Queryer) -> Option<serde_json::Value> { + fn look_up_user(&mut self, id: &str, queryer: &mut ::Queryer) -> Result<serde_json::Value, String> { let url = &format!("{}?user_id={}", ::USER_LOOKUP_URL, id); queryer.do_api_get(url) } - fn look_up_tweet(&mut self, id: &str, queryer: &mut ::Queryer) -> Option<serde_json::Value> { + fn look_up_tweet(&mut self, id: &str, queryer: &mut ::Queryer) -> Result<serde_json::Value, String> { let url = &format!("{}&id={}", ::TWEET_LOOKUP_URL, id); queryer.do_api_get(url) } - pub fn get_settings(&self, queryer: &mut ::Queryer) -> Option<serde_json::Value> { + pub fn get_settings(&self, queryer: &mut ::Queryer) -> Result<serde_json::Value, String> { queryer.do_api_get(::ACCOUNT_SETTINGS_URL) } - pub fn get_followers(&self, queryer: &mut ::Queryer) -> Option<serde_json::Value> { + pub fn get_followers(&self, queryer: &mut ::Queryer) -> Result<serde_json::Value, String> { queryer.do_api_get(::GET_FOLLOWER_IDS_URL) } @@ -684,7 +664,6 @@ fn handle_twitter_welcome( structure: serde_json::Map<String, serde_json::Value>, tweeter: &mut TwitterCache, queryer: &mut ::Queryer) { -// println!("welcome: {:?}", structure); let user_id_nums = structure["friends"].as_array().unwrap(); let user_id_strs = user_id_nums.into_iter().map(|x| x.as_u64().unwrap().to_string()); tweeter.set_following(user_id_strs.collect()); @@ -722,6 +701,8 @@ pub fn handle_message( handle_twitter_twete(objmap, tweeter, queryer); } else if objmap.contains_key("direct_message") { handle_twitter_dm(objmap, tweeter, queryer); + } else { + tweeter.display_info.status(format!("Unknown json: {:?}", objmap)); } // self.display_info.status(""); }, diff --git a/src/tw/tweet.rs b/src/tw/tweet.rs index a3fdde3..dc89774 100644 --- a/src/tw/tweet.rs +++ b/src/tw/tweet.rs @@ -38,14 +38,17 @@ impl Tweet { .collect() } - pub fn from_api_json(json: serde_json::Value) -> Option<(Tweet, User)> { + pub fn from_api_json(json: serde_json::Value) -> Result<(Tweet, User), String> { Tweet::from_json(json.clone()).and_then(|tw| { - json.get("user").and_then(|user_json| - User::from_json(user_json.to_owned()).map(|u| (tw, u)) - ) + match json.get("user") { + Some(user_json) => + User::from_json(user_json.to_owned()).map(|u| (tw, u)), + None => + Err("No user json".to_owned()) + } }) } - pub fn from_json(json: serde_json::Value) -> Option<Tweet> { + pub fn from_json(json: serde_json::Value) -> Result<Tweet, String> { if let serde_json::Value::Object(json_map) = json { let text = ::tw::full_twete_text(&json_map); let rt_twete = json_map.get("retweeted_status") @@ -67,7 +70,7 @@ impl Tweet { json_map["user"]["id_str"].as_str(), json_map["created_at"].as_str() ) { - return Some(Tweet { + return Ok(Tweet { id: id_str.to_owned(), author_id: author_id.to_owned(), text: text, @@ -82,6 +85,6 @@ impl Tweet { } } } - None + Err("Invalid tweet json".to_owned()) } } diff --git a/src/tw/user.rs b/src/tw/user.rs index 8f41b6d..0af4eb8 100644 --- a/src/tw/user.rs +++ b/src/tw/user.rs @@ -18,29 +18,28 @@ impl Default for User { } impl User { - pub fn from_json(json: serde_json::Value) -> Option<User> { + pub fn from_json(json: serde_json::Value) -> Result<User, String> { if let serde_json::Value::Object(json_map) = json { - if json_map.contains_key("id_str") && - json_map.contains_key("name") && - json_map.contains_key("screen_name") { - if let ( - Some(id_str), - Some(name), - Some(screen_name) - ) = ( - json_map["id_str"].as_str(), - json_map["name"].as_str(), - json_map["screen_name"].as_str() - ) { - return Some(User { - id: id_str.to_owned(), - name: name.to_owned(), - handle: screen_name.to_owned() - }) - } + if let ( + Some(id_str), + Some(name), + Some(screen_name) + ) = ( + json_map.get("id_str").and_then(|x| x.as_str()), + json_map.get("name").and_then(|x| x.as_str()), + json_map.get("screen_name").and_then(|x| x.as_str()) + ) { + Ok(User { + id: id_str.to_owned(), + name: name.to_owned(), + handle: screen_name.to_owned() + }) + } else { + Err("user json missing one of id_str, name, screen_name".to_owned()) } + } else { + Err(format!("Invalid json: {:?}", json)) } - None } } |