From afd61ae0822690f30d37859c806a8d8d843b8c1a Mon Sep 17 00:00:00 2001 From: Andy Wortman Date: Sun, 1 Oct 2017 23:51:13 -0700 Subject: extract twitter message handling logic --- display/mod.rs | 7 +- main.rs | 91 +------------------------ tw/mod.rs | 207 +++++++++++++++++++++++++-------------------------------- tw/tweet.rs | 78 ++++++++++++++++++++++ tw/user.rs | 46 +++++++++++++ 5 files changed, 221 insertions(+), 208 deletions(-) create mode 100644 tw/tweet.rs create mode 100644 tw/user.rs diff --git a/display/mod.rs b/display/mod.rs index 715c4d3..24f7e33 100644 --- a/display/mod.rs +++ b/display/mod.rs @@ -33,7 +33,6 @@ pub trait Render { impl Render for tw::events::Event { fn render(self, tweeter: &::tw::TwitterCache) { - println!("---------------------------------"); match self { tw::events::Event::Deleted { user_id, twete_id } => { if let Some(handle) = tweeter.retrieve_user(&user_id).map(|x| &x.handle) { @@ -50,30 +49,36 @@ impl Render for tw::events::Event { } }, tw::events::Event::RT_RT { user_id, twete_id } => { + println!("---------------------------------"); let user = tweeter.retrieve_user(&user_id).unwrap(); println!(" +rt_rt : {} (@{})", user.name, user.handle); render_twete(&twete_id, tweeter); }, tw::events::Event::Fav_RT { user_id, twete_id } => { + println!("---------------------------------"); let user = tweeter.retrieve_user(&user_id).unwrap(); println!(" +rt_fav : {} (@{})", user.name, user.handle); render_twete(&twete_id, tweeter); }, tw::events::Event::Fav { user_id, twete_id } => { + println!("---------------------------------"); let user = tweeter.retrieve_user(&user_id).unwrap(); println!("{} +fav : {} (@{}){}", color::Fg(color::Yellow), user.name, user.handle, color::Fg(color::Reset)); render_twete(&twete_id, tweeter); }, tw::events::Event::Unfav { user_id, twete_id } => { + println!("---------------------------------"); let user = tweeter.retrieve_user(&user_id).unwrap(); println!("{} -fav : {} (@{}){}", color::Fg(color::Yellow), user.name, user.handle, color::Fg(color::Reset)); render_twete(&twete_id, tweeter); }, tw::events::Event::Followed { user_id } => { + println!("---------------------------------"); let user = tweeter.retrieve_user(&user_id).unwrap(); println!(" +fl : {} (@{})", user.name, user.handle); }, tw::events::Event::Unfollowed { user_id } => { + println!("---------------------------------"); let user = tweeter.retrieve_user(&user_id).unwrap(); println!(" -fl : {} (@{})", user.name, user.handle); } diff --git a/main.rs b/main.rs index da10fdf..37082a1 100644 --- a/main.rs +++ b/main.rs @@ -28,7 +28,6 @@ use linestream::LineStream; mod tw; mod display; -use display::Render; //Change these values to your real Twitter API credentials static consumer_key: &str = "T879tHWDzd6LvKWdYVfbJL4Su"; @@ -96,83 +95,6 @@ impl Queryer { } } -fn handle_twitter_event( - structure: serde_json::Map, - tweeter: &mut tw::TwitterCache, - mut queryer: &mut Queryer) { - tweeter.cache_api_event(structure.clone(), &mut queryer); - if let Some(event) = tw::events::Event::from_json(structure) { - event.render(&tweeter); - }; -} - -fn handle_twitter_delete( - structure: serde_json::Map, - tweeter: &mut tw::TwitterCache, - _queryer: &mut Queryer) { - tw::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() - }.render(tweeter); -} - -fn handle_twitter_twete( - structure: serde_json::Map, - tweeter: &mut tw::TwitterCache, - _queryer: &mut Queryer) { - let twete_id = structure["id_str"].as_str().unwrap().to_string(); - tweeter.cache_api_tweet(serde_json::Value::Object(structure)); - display::render_twete(&twete_id, tweeter); -} - -fn handle_twitter_dm( - structure: serde_json::Map, - _tweeter: &mut tw::TwitterCache, - _queryer: &mut Queryer) { - // show DM - println!("{}", structure["direct_message"]["text"].as_str().unwrap()); - println!("Unknown struture {:?}", structure); -} - -fn handle_twitter_welcome( - structure: serde_json::Map, - tweeter: &mut tw::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()); - let settings = tweeter.get_settings(queryer).unwrap(); - let maybe_my_name = settings["screen_name"].as_str(); - if let Some(my_name) = maybe_my_name { - tweeter.current_user = tw::User { - id: "".to_string(), - handle: my_name.to_owned(), - name: my_name.to_owned() - }; - println!("You are {}", tweeter.current_user.handle); - } else { - println!("Unable to make API call to figure out who you are..."); - } -} - -fn handle_twitter( - structure: serde_json::Map, - tweeter: &mut tw::TwitterCache, - queryer: &mut Queryer) { - if structure.contains_key("event") { - handle_twitter_event(structure, tweeter, queryer); - } else if structure.contains_key("friends") { - handle_twitter_welcome(structure, tweeter, queryer); - } else if structure.contains_key("delete") { - handle_twitter_delete(structure, tweeter, queryer); - } else if structure.contains_key("user") && structure.contains_key("id") { - handle_twitter_twete(structure, tweeter, queryer); - } else if structure.contains_key("direct_message") { - handle_twitter_dm(structure, tweeter, queryer); - } - println!(""); -} /* fn signed_web_get(url: &str) -> hyper::client::Request { // let params: Vec<(String, String)> = vec![("track".to_string(), "london".to_string())]; @@ -251,17 +173,6 @@ fn signed_api_req(url: &str, method: Method) -> hyper::client::Request { req } -fn display_event( - twete: serde_json::Value, - tweeter: &mut tw::TwitterCache, - queryer: &mut Queryer -) { - match twete { - serde_json::Value::Object(objmap) => handle_twitter(objmap, tweeter, queryer), - _ => () - }; -} - fn main() { //Track words @@ -333,7 +244,7 @@ fn do_ui(ui_rx_orig: chan::Receiver>, twete_rx: chan::Receiver>, // println!("{}", jsonstr); /* TODO: replace from_str with from_slice */ let json: serde_json::Value = serde_json::from_str(&jsonstr).unwrap(); - display_event(json, &mut tweeter, &mut queryer); + tw::handle_message(json, &mut tweeter, &mut queryer); if tweeter.needs_save && tweeter.caching_permitted { tweeter.store_cache(); } diff --git a/tw/mod.rs b/tw/mod.rs index 540d4d0..eff38e7 100644 --- a/tw/mod.rs +++ b/tw/mod.rs @@ -13,124 +13,13 @@ use std::fs::OpenOptions; pub mod events; -#[derive(Debug, Serialize, Deserialize)] -pub struct User { - pub id: String, - pub name: String, - pub handle: String -} - -impl Default for User { - fn default() -> User { - User { - id: "".to_owned(), - name: "_default_".to_owned(), - handle: "_default_".to_owned() - } - } -} - -impl User { - pub fn from_json(json: serde_json::Value) -> Option { - 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() - }) - } - } - } - None - } -} +use display::Render; +use display; -#[derive(Debug, Serialize, Deserialize)] -pub struct Tweet { - pub id: String, - pub author_id: String, - pub text: String, - pub created_at: String, // lol - #[serde(skip_serializing_if="Option::is_none")] - #[serde(default = "Option::default")] - pub quoted_tweet_id: Option, - #[serde(skip_serializing_if="Option::is_none")] - #[serde(default = "Option::default")] - pub rt_tweet: Option, - #[serde(skip)] - pub internal_id: u64 -} - -impl Tweet { - pub fn get_mentions(&self) -> Vec<&str> { - self.text.split(&[ - ',', '.', '/', ';', '\'', - '[', ']', '\\', '~', '!', - '@', '#', '$', '%', '^', - '&', '*', '(', ')', '-', - '=', '{', '}', '|', ':', - '"', '<', '>', '?', '`', - ' ' // forgot this initially. awkward. - ][..]) - .filter(|x| x.starts_with("@") && x.len() > 1) - .collect() - } - - pub fn from_api_json(json: serde_json::Value) -> Option<(Tweet, User)> { - 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)) - ) - }) - } - pub fn from_json(json: serde_json::Value) -> Option { - if let serde_json::Value::Object(json_map) = json { - let text = full_twete_text(&json_map); - let rt_twete = json_map.get("retweeted_status") - .and_then(|x| x.get("id_str")) - .and_then(|x| x.as_str()) - .map(|x| x.to_owned()); - if json_map.contains_key("id_str") && - json_map.contains_key("user") && - json_map.contains_key("created_at") { - if let ( - Some(id_str), - Some(author_id), - Some(created_at) - ) = ( - json_map["id_str"].as_str(), - json_map["user"]["id_str"].as_str(), - json_map["created_at"].as_str() - ) { - return Some(Tweet { - id: id_str.to_owned(), - author_id: author_id.to_owned(), - text: text, - created_at: created_at.to_owned(), - quoted_tweet_id: json_map.get("quoted_status_id_str") - .and_then(|x| x.as_str()) - .map(|x| x.to_owned()), - rt_tweet: rt_twete, - internal_id: 0 - }) - } - } - } - None - } -} +pub mod tweet; +use self::tweet::Tweet; +pub mod user; +use self::user::User; pub fn full_twete_text(twete: &serde_json::map::Map) -> String { if twete.contains_key("retweeted_status") { @@ -465,3 +354,87 @@ impl TwitterCache { queryer.do_api_get(::ACCOUNT_SETTINGS_URL) } } + +fn handle_twitter_event( + structure: serde_json::Map, + tweeter: &mut TwitterCache, + mut queryer: &mut ::Queryer) { + tweeter.cache_api_event(structure.clone(), &mut queryer); + if let Some(event) = events::Event::from_json(structure) { + event.render(&tweeter); + }; +} + +fn handle_twitter_delete( + structure: serde_json::Map, + tweeter: &mut TwitterCache, + _queryer: &mut ::Queryer) { + 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() + }.render(tweeter); +} + +fn handle_twitter_twete( + structure: serde_json::Map, + tweeter: &mut TwitterCache, + _queryer: &mut ::Queryer) { + let twete_id = structure["id_str"].as_str().unwrap().to_string(); + tweeter.cache_api_tweet(serde_json::Value::Object(structure)); + display::render_twete(&twete_id, tweeter); +} + +fn handle_twitter_dm( + structure: serde_json::Map, + _tweeter: &mut TwitterCache, + _queryer: &mut ::Queryer) { + // show DM + println!("{}", structure["direct_message"]["text"].as_str().unwrap()); + println!("Unknown struture {:?}", structure); +} + +fn handle_twitter_welcome( + structure: serde_json::Map, + 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()); + let settings = tweeter.get_settings(queryer).unwrap(); + let maybe_my_name = settings["screen_name"].as_str(); + if let Some(my_name) = maybe_my_name { + tweeter.current_user = User { + id: "".to_string(), + handle: my_name.to_owned(), + name: my_name.to_owned() + }; + println!("You are {}", tweeter.current_user.handle); + } else { + println!("Unable to make API call to figure out who you are..."); + } +} + +pub fn handle_message( + twete: serde_json::Value, + tweeter: &mut TwitterCache, + queryer: &mut ::Queryer +) { + match twete { + serde_json::Value::Object(objmap) => { + if objmap.contains_key("event") { + handle_twitter_event(objmap, tweeter, queryer); + } else if objmap.contains_key("friends") { + handle_twitter_welcome(objmap, tweeter, queryer); + } else if objmap.contains_key("delete") { + handle_twitter_delete(objmap, tweeter, queryer); + } else if objmap.contains_key("user") && objmap.contains_key("id") { + handle_twitter_twete(objmap, tweeter, queryer); + } else if objmap.contains_key("direct_message") { + handle_twitter_dm(objmap, tweeter, queryer); + } + println!(""); + }, + _ => () + }; +} diff --git a/tw/tweet.rs b/tw/tweet.rs new file mode 100644 index 0000000..778461a --- /dev/null +++ b/tw/tweet.rs @@ -0,0 +1,78 @@ +extern crate serde_json; + +use tw::user::User; + +#[derive(Debug, Serialize, Deserialize)] +pub struct Tweet { + pub id: String, + pub author_id: String, + pub text: String, + pub created_at: String, // lol + #[serde(skip_serializing_if="Option::is_none")] + #[serde(default = "Option::default")] + pub quoted_tweet_id: Option, + #[serde(skip_serializing_if="Option::is_none")] + #[serde(default = "Option::default")] + pub rt_tweet: Option, + #[serde(skip)] + pub internal_id: u64 +} + +impl Tweet { + pub fn get_mentions(&self) -> Vec<&str> { + self.text.split(&[ + ',', '.', '/', ';', '\'', + '[', ']', '\\', '~', '!', + '@', '#', '$', '%', '^', + '&', '*', '(', ')', '-', + '=', '{', '}', '|', ':', + '"', '<', '>', '?', '`', + ' ' // forgot this initially. awkward. + ][..]) + .filter(|x| x.starts_with("@") && x.len() > 1) + .collect() + } + + pub fn from_api_json(json: serde_json::Value) -> Option<(Tweet, User)> { + 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)) + ) + }) + } + pub fn from_json(json: serde_json::Value) -> Option { + 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") + .and_then(|x| x.get("id_str")) + .and_then(|x| x.as_str()) + .map(|x| x.to_owned()); + if json_map.contains_key("id_str") && + json_map.contains_key("user") && + json_map.contains_key("created_at") { + if let ( + Some(id_str), + Some(author_id), + Some(created_at) + ) = ( + json_map["id_str"].as_str(), + json_map["user"]["id_str"].as_str(), + json_map["created_at"].as_str() + ) { + return Some(Tweet { + id: id_str.to_owned(), + author_id: author_id.to_owned(), + text: text, + created_at: created_at.to_owned(), + quoted_tweet_id: json_map.get("quoted_status_id_str") + .and_then(|x| x.as_str()) + .map(|x| x.to_owned()), + rt_tweet: rt_twete, + internal_id: 0 + }) + } + } + } + None + } +} diff --git a/tw/user.rs b/tw/user.rs new file mode 100644 index 0000000..1da82f0 --- /dev/null +++ b/tw/user.rs @@ -0,0 +1,46 @@ +extern crate serde_json; + +#[derive(Debug, Serialize, Deserialize)] +pub struct User { + pub id: String, + pub name: String, + pub handle: String +} + +impl Default for User { + fn default() -> User { + User { + id: "".to_owned(), + name: "_default_".to_owned(), + handle: "_default_".to_owned() + } + } +} + +impl User { + pub fn from_json(json: serde_json::Value) -> Option { + 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() + }) + } + } + } + None + } +} + -- cgit v1.1