From 943824e02fa771fa8350e4da90f2c9591ec4647e Mon Sep 17 00:00:00 2001 From: Andy Wortman Date: Sun, 1 Oct 2017 23:25:46 -0700 Subject: yank out more parts, decouple events and display --- commands/view.rs | 4 +- display/mod.rs | 142 ++++++++++++++++++++++++++++++++ linestream.rs | 42 ++++++++++ main.rs | 244 ++++++++++++++++--------------------------------------- tw/events.rs | 44 ++++++++++ tw/mod.rs | 157 +---------------------------------- 6 files changed, 301 insertions(+), 332 deletions(-) create mode 100644 display/mod.rs create mode 100644 linestream.rs create mode 100644 tw/events.rs diff --git a/commands/view.rs b/commands/view.rs index 1470f90..d01ff1b 100644 --- a/commands/view.rs +++ b/commands/view.rs @@ -5,6 +5,8 @@ use commands::Command; use std::str::FromStr; +use display; + pub static VIEW: Command = Command { keyword: "view", params: 1, @@ -15,6 +17,6 @@ fn view(line: String, tweeter: &mut tw::TwitterCache, _queryer: &mut Queryer) { // TODO handle this unwrap let inner_twid = u64::from_str(&line).unwrap(); let twete = tweeter.tweet_by_innerid(inner_twid).unwrap(); - ::render_twete(&twete.id, tweeter); + display::render_twete(&twete.id, tweeter); println!("link: https://twitter.com/i/web/status/{}", twete.id); } diff --git a/display/mod.rs b/display/mod.rs new file mode 100644 index 0000000..715c4d3 --- /dev/null +++ b/display/mod.rs @@ -0,0 +1,142 @@ +extern crate termion; + +use self::termion::color; + +use ::tw; + +use std; + +fn color_for(handle: &String) -> termion::color::Fg<&color::Color> { + let color_map: Vec<&color::Color> = vec![ + &color::Blue, + &color::Cyan, + &color::Green, + &color::LightBlue, + &color::LightCyan, + &color::LightGreen, + &color::LightMagenta, + &color::LightYellow, + &color::Magenta, + &color::Yellow + ]; + + let mut quot_hash_quot = std::num::Wrapping(0); + for b in handle.as_bytes().iter() { + quot_hash_quot = quot_hash_quot + std::num::Wrapping(*b); + } + color::Fg(color_map[quot_hash_quot.0 as usize % color_map.len()]) +} + +pub trait Render { + fn render(self, tweeter: &::tw::TwitterCache); +} + +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) { + if let Some(_tweet) = tweeter.retrieve_tweet(&twete_id) { + println!("-------------DELETED------------------"); + render_twete(&twete_id, tweeter); + println!("-------------DELETED------------------"); + } else { + println!("dunno what, but do know who: {} - {}", user_id, handle); + } + } else { + println!("delete..."); + println!("dunno who..."); + } + }, + tw::events::Event::RT_RT { user_id, twete_id } => { + 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 } => { + 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 } => { + 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 } => { + 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 } => { + let user = tweeter.retrieve_user(&user_id).unwrap(); + println!(" +fl : {} (@{})", user.name, user.handle); + }, + tw::events::Event::Unfollowed { user_id } => { + let user = tweeter.retrieve_user(&user_id).unwrap(); + println!(" -fl : {} (@{})", user.name, user.handle); + } + /* + Blocked(user_id) => { + }, + */ + } + println!(""); + } +} + +pub fn render_twete(twete_id: &String, tweeter: &tw::TwitterCache) { + let id_color = color::Fg(color::Rgb(180, 80, 40)); + let twete = tweeter.retrieve_tweet(twete_id).unwrap(); + // if we got the tweet, the API gave us the user too + let user = tweeter.retrieve_user(&twete.author_id).unwrap(); + match twete.rt_tweet { + Some(ref rt_id) => { + // same for a retweet + let rt = tweeter.retrieve_tweet(rt_id).unwrap(); + // and its author + let rt_author = tweeter.retrieve_user(&rt.author_id).unwrap(); + println!("{} id:{} (rt_id:{}){}", + id_color, rt.internal_id, twete.internal_id, color::Fg(color::Reset) + ); + println!(" {}{}{} ({}@{}{}) 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), + color_for(&user.handle), user.name, color::Fg(color::Reset), + color_for(&user.handle), user.handle, color::Fg(color::Reset) + ); + } + None => { + println!("{} id:{}{}", + id_color, twete.internal_id, color::Fg(color::Reset) + ); + println!(" {}{}{} ({}@{}{})", + color_for(&user.handle), user.name, color::Fg(color::Reset), + color_for(&user.handle), user.handle, color::Fg(color::Reset) + ); + } + } + + println!(" {}", twete.text.replace("\r", "\\r").split("\n").collect::>().join("\n ")); + + if let Some(ref qt_id) = twete.quoted_tweet_id { + if let Some(ref qt) = tweeter.retrieve_tweet(qt_id) { + let qt_author = tweeter.retrieve_user(&qt.author_id).unwrap(); + println!("{} id:{}{}", + id_color, qt.internal_id, color::Fg(color::Reset) + ); + println!( + " {}{}{} ({}@{}{})", + color_for(&qt_author.handle), qt_author.name, color::Fg(color::Reset), + color_for(&qt_author.handle), qt_author.handle, color::Fg(color::Reset) + ); + println!( + " {}", + qt.text.replace("\r", "\\r").split("\n").collect::>().join("\n ") + ); + } else { + println!(" << don't have quoted tweet! >>"); + } + } +} diff --git a/linestream.rs b/linestream.rs new file mode 100644 index 0000000..5106af3 --- /dev/null +++ b/linestream.rs @@ -0,0 +1,42 @@ +use std; +use futures::stream::Stream; +use futures::{Poll, Async}; + +pub struct LineStream where S: Stream { + stream: S, + progress: Vec +} + +impl LineStream where S: Stream + Sized { + pub fn new(stream: S) -> LineStream { + LineStream { + stream: stream, + progress: vec![] + } + } +} + +impl Stream for LineStream where S: Stream { + type Item = Vec; + type Error = E; + + fn poll(&mut self) -> Poll, Self::Error> { + loop { + match self.stream.poll() { + Ok(Async::Ready(Some(byte))) => { + if byte == 0x0a { + let mut new_vec = vec![]; + std::mem::swap(&mut self.progress, &mut new_vec); + return Ok(Async::Ready(Some(new_vec))) + } else { + self.progress.push(byte) + } + }, + Ok(Async::Ready(None)) => return Ok(Async::Ready(None)), + Ok(Async::NotReady) => return Ok(Async::NotReady), + Err(e) => return Err(e) + } + } + } +} + diff --git a/main.rs b/main.rs index 5b5f493..da10fdf 100644 --- a/main.rs +++ b/main.rs @@ -23,7 +23,12 @@ use futures::Stream; use hyper_tls::HttpsConnector; //use json_streamer::JsonObjectStreamer; +mod linestream; +use linestream::LineStream; + mod tw; +mod display; +use display::Render; //Change these values to your real Twitter API credentials static consumer_key: &str = "T879tHWDzd6LvKWdYVfbJL4Su"; @@ -91,136 +96,80 @@ impl Queryer { } } -extern crate termion; - -use termion::color; - -fn color_for(handle: &String) -> termion::color::Fg<&color::Color> { - let color_map: Vec<&color::Color> = vec![ - &color::Blue, - &color::Cyan, - &color::Green, - &color::LightBlue, - &color::LightCyan, - &color::LightGreen, - &color::LightMagenta, - &color::LightYellow, - &color::Magenta, - &color::Yellow - ]; - - let mut quot_hash_quot = std::num::Wrapping(0); - for b in handle.as_bytes().iter() { - quot_hash_quot = quot_hash_quot + std::num::Wrapping(*b); - } - color::Fg(color_map[quot_hash_quot.0 as usize % color_map.len()]) +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 render_twete(twete_id: &String, tweeter: &tw::TwitterCache) { - let id_color = color::Fg(color::Rgb(180, 80, 40)); - let twete = tweeter.retrieve_tweet(twete_id).unwrap(); - // if we got the tweet, the API gave us the user too - let user = tweeter.retrieve_user(&twete.author_id).unwrap(); - match twete.rt_tweet { - Some(ref rt_id) => { - // same for a retweet - let rt = tweeter.retrieve_tweet(rt_id).unwrap(); - // and its author - let rt_author = tweeter.retrieve_user(&rt.author_id).unwrap(); - println!("{} id:{} (rt_id:{}){}", - id_color, rt.internal_id, twete.internal_id, color::Fg(color::Reset) - ); - println!(" {}{}{} ({}@{}{}) 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), - color_for(&user.handle), user.name, color::Fg(color::Reset), - color_for(&user.handle), user.handle, color::Fg(color::Reset) - ); - } - None => { - println!("{} id:{}{}", - id_color, twete.internal_id, color::Fg(color::Reset) - ); - println!(" {}{}{} ({}@{}{})", - color_for(&user.handle), user.name, color::Fg(color::Reset), - color_for(&user.handle), user.handle, color::Fg(color::Reset) - ); - } - } +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); +} - println!(" {}", twete.text.replace("\r", "\\r").split("\n").collect::>().join("\n ")); - - if let Some(ref qt_id) = twete.quoted_tweet_id { - if let Some(ref qt) = tweeter.retrieve_tweet(qt_id) { - let qt_author = tweeter.retrieve_user(&qt.author_id).unwrap(); - println!("{} id:{}{}", - id_color, qt.internal_id, color::Fg(color::Reset) - ); - println!( - " {}{}{} ({}@{}{})", - color_for(&qt_author.handle), qt_author.name, color::Fg(color::Reset), - color_for(&qt_author.handle), qt_author.handle, color::Fg(color::Reset) - ); - println!( - " {}", - qt.text.replace("\r", "\\r").split("\n").collect::>().join("\n ") - ); - } else { - println!(" << don't have quoted tweet! >>"); - } +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 render_twitter_event( +fn handle_twitter( structure: serde_json::Map, tweeter: &mut tw::TwitterCache, - mut queryer: &mut Queryer) { + queryer: &mut Queryer) { if structure.contains_key("event") { - tweeter.cache_api_event(structure.clone(), &mut queryer); - if let Some(event) = tw::events::Event::from_json(structure) { - event.render(&tweeter); - }; + handle_twitter_event(structure, tweeter, queryer); } else if structure.contains_key("friends") { -// 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..."); - } + handle_twitter_welcome(structure, tweeter, queryer); } else if structure.contains_key("delete") { - let deleted_user_id = structure["delete"]["status"]["user_id_str"].as_str().unwrap().to_string(); - let deleted_tweet_id = structure["delete"]["status"]["id_str"].as_str().unwrap().to_string(); - if let Some(handle) = tweeter.retrieve_user(&deleted_user_id).map(|x| &x.handle) { - if let Some(_tweet) = tweeter.retrieve_tweet(&deleted_tweet_id) { - println!("-------------DELETED------------------"); - render_twete(&deleted_tweet_id, tweeter); - println!("-------------DELETED------------------"); - } else { - println!("dunno what, but do know who: {} - {}", deleted_user_id, handle); - } - } else { - println!("delete..."); - println!("dunno who..."); - } + handle_twitter_delete(structure, tweeter, queryer); } else if structure.contains_key("user") && structure.contains_key("id") { - let twete_id = structure["id_str"].as_str().unwrap().to_string(); - tweeter.cache_api_tweet(serde_json::Value::Object(structure)); - render_twete(&twete_id, tweeter); + handle_twitter_twete(structure, tweeter, queryer); } else if structure.contains_key("direct_message") { - // show DM - println!("{}", structure["direct_message"]["text"].as_str().unwrap()); - println!("Unknown struture {:?}", structure); + handle_twitter_dm(structure, tweeter, queryer); } println!(""); } @@ -308,7 +257,7 @@ fn display_event( queryer: &mut Queryer ) { match twete { - serde_json::Value::Object(objmap) => render_twitter_event(objmap, tweeter, queryer), + serde_json::Value::Object(objmap) => handle_twitter(objmap, tweeter, queryer), _ => () }; } @@ -417,8 +366,9 @@ fn do_ui(ui_rx_orig: chan::Receiver>, twete_rx: chan::Receiver>, fn url_encode(s: &str) -> String { s - .replace(" ", "+") .replace("%", "%25") + .replace("+", "%2b") + .replace(" ", "+") .replace("\\n", "%0a") .replace("\\r", "%0d") .replace("\\esc", "%1b") @@ -429,7 +379,6 @@ fn url_encode(s: &str) -> String { .replace("(", "%28") .replace(")", "%29") .replace("*", "%2a") -// .replace("+", "%2b") .replace(",", "%2c") .replace("-", "%2d") .replace(".", "%2e") @@ -520,60 +469,3 @@ fn connect_twitter_stream() -> chan::Receiver> { twete_rx } - -//extern crate futures; -//use futures::stream::Stream; -//use futures::{Future, Poll, Async}; -use futures::{Poll, Async}; -/* -fn main() { - let lines = "line 1.\nline 2...\n LINE 3 \n".as_bytes(); - let bytestream = futures::stream::iter(lines.iter().map(|byte| -> Result<_, ()> { Ok(*byte) })); - let linestream = LineStream::new(bytestream); - - linestream.for_each(|line| { - println!("Bytes: {:?}", line); - println!("Line: {}", String::from_utf8(line).unwrap()); - Ok(()) - }).wait().unwrap() -} -*/ - -struct LineStream where S: Stream { - stream: S, - progress: Vec -} - -impl LineStream where S: Stream + Sized { - pub fn new(stream: S) -> LineStream { - LineStream { - stream: stream, - progress: vec![] - } - } -} - -impl Stream for LineStream where S: Stream { - type Item = Vec; - type Error = E; - - fn poll(&mut self) -> Poll, Self::Error> { - loop { - match self.stream.poll() { - Ok(Async::Ready(Some(byte))) => { - if byte == 0x0a { - let mut new_vec = vec![]; - std::mem::swap(&mut self.progress, &mut new_vec); - return Ok(Async::Ready(Some(new_vec))) - } else { - self.progress.push(byte) - } - }, - Ok(Async::Ready(None)) => return Ok(Async::Ready(None)), - Ok(Async::NotReady) => return Ok(Async::NotReady), - Err(e) => return Err(e) - } - } - } -} - diff --git a/tw/events.rs b/tw/events.rs new file mode 100644 index 0000000..0541b0a --- /dev/null +++ b/tw/events.rs @@ -0,0 +1,44 @@ +extern crate serde_json; + +pub enum Event { + Deleted { user_id: String, twete_id: String }, + RT_RT { user_id: String, twete_id: String }, + Fav_RT { user_id: String, twete_id: String }, + Fav { user_id: String, twete_id: String }, + Unfav { user_id: String, twete_id: String }, + Followed { user_id: String }, + Unfollowed { user_id: String } +} + +impl Event { + pub fn from_json(structure: serde_json::Map) -> Option { + match &structure["event"].as_str().unwrap() { + &"follow" => Some(Event::Followed { + user_id: structure["source"]["id_str"].as_str().unwrap().to_owned() + }), + &"unfollow" => Some(Event::Unfollowed { + user_id: structure["source"]["id_str"].as_str().unwrap().to_owned() + }), + &"favorite" => Some(Event::Fav { + user_id: structure["source"]["id_str"].as_str().unwrap().to_owned(), + twete_id: structure["target_object"]["id_str"].as_str().unwrap().to_owned() + }), + &"unfavorite" => Some(Event::Unfav { + user_id: structure["source"]["id_str"].as_str().unwrap().to_owned(), + twete_id: structure["target_object"]["id_str"].as_str().unwrap().to_owned() + }), + &"favorited_retweet" => Some(Event::Fav_RT { + user_id: structure["source"]["id_str"].as_str().unwrap().to_owned(), + twete_id: structure["target_object"]["id_str"].as_str().unwrap().to_owned() + }), + &"retweeted_retweet" => Some(Event::RT_RT { + user_id: structure["source"]["id_str"].as_str().unwrap().to_owned(), + twete_id: structure["target_object"]["id_str"].as_str().unwrap().to_owned() + }), +// &"blocked" => Blocked { }, +// &"unblocked" => Unblocked { }, +// &"quoted_tweet" => ???, + e => { println!("unrecognized event: {}", e); None } + } + } +} diff --git a/tw/mod.rs b/tw/mod.rs index efc070b..540d4d0 100644 --- a/tw/mod.rs +++ b/tw/mod.rs @@ -11,6 +11,8 @@ use std::io::Write; use std::fs::OpenOptions; +pub mod events; + #[derive(Debug, Serialize, Deserialize)] pub struct User { pub id: String, @@ -28,161 +30,6 @@ impl Default for User { } } -pub mod events { - extern crate termion; - use self::termion::color; - - extern crate serde_json; - - pub struct Deleted { - user_id: String, - twete_id: String - } - - pub struct RT_RT { - user_id: String, - twete_id: String - } - - pub struct Fav_RT { - user_id: String, - twete_id: String - } - - pub struct Fav { - user_id: String, - twete_id: String - } - - pub struct Unfav { - user_id: String, - twete_id: String - } - - pub struct Followed { - user_id: String - } - - pub struct Unfollowed { - user_id: String - } - - impl Event for Deleted { - fn render(self: Box, _tweeter: &::tw::TwitterCache) { } - } - impl Event for RT_RT { - fn render(self: Box, tweeter: &::tw::TwitterCache) { - println!("---------------------------------"); - { - let user = tweeter.retrieve_user(&self.user_id).unwrap(); - println!(" +rt_rt : {} (@{})", user.name, user.handle); - } - { - ::render_twete(&self.twete_id, tweeter); - } - println!(""); - } - } - impl Event for Fav_RT { - fn render(self: Box, tweeter: &::tw::TwitterCache) { - println!("---------------------------------"); - { - let user = tweeter.retrieve_user(&self.user_id).unwrap(); - println!(" +rt_fav : {} (@{})", user.name, user.handle); - } - { - ::render_twete(&self.twete_id, tweeter); - } - println!(""); - } - } - impl Event for Fav { - fn render(self: Box, tweeter: &::tw::TwitterCache) { - println!("---------------------------------"); - { - let user = tweeter.retrieve_user(&self.user_id).unwrap(); - println!("{} +fav : {} (@{}){}", color::Fg(color::Yellow), user.name, user.handle, color::Fg(color::Reset)); - } - { - ::render_twete(&self.twete_id, tweeter); - } - println!(""); - } - } - impl Event for Unfav { - fn render(self: Box, tweeter: &::tw::TwitterCache) { - println!("---------------------------------"); - { - let user = tweeter.retrieve_user(&self.user_id).unwrap(); - println!("{} -fav : {} (@{}){}", color::Fg(color::Yellow), user.name, user.handle, color::Fg(color::Reset)); - } - { - ::render_twete(&self.twete_id, tweeter); - } - println!(""); - } - } - impl Event for Followed { - fn render(self: Box, tweeter: &::tw::TwitterCache) { - let user = tweeter.retrieve_user(&self.user_id).unwrap(); - println!("---------------------------------"); - println!(" +fl : {} (@{})", user.name, user.handle); - println!(""); - } - } - impl Event for Unfollowed { - fn render(self: Box, tweeter: &::tw::TwitterCache) { - let user = tweeter.retrieve_user(&self.user_id).unwrap(); - println!("---------------------------------"); - println!(" -fl : {} (@{})", user.name, user.handle); - println!(""); - } - } - - /* - impl Event for Blocked { - - } - */ - - pub trait Event { - fn render(self: Box, tweeter: &::tw::TwitterCache); - } - - impl Event { - pub fn from_json(structure: serde_json::Map) -> Option> { - match &structure["event"].as_str().unwrap() { - &"follow" => Some(Box::new(Followed { - user_id: structure["source"]["id_str"].as_str().unwrap().to_owned() - })), - &"unfollow" => Some(Box::new(Unfollowed { - user_id: structure["source"]["id_str"].as_str().unwrap().to_owned() - })), - &"favorite" => Some(Box::new(Fav { - user_id: structure["source"]["id_str"].as_str().unwrap().to_owned(), - twete_id: structure["target_object"]["id_str"].as_str().unwrap().to_owned() - })), - &"unfavorite" => Some(Box::new(Unfav { - user_id: structure["source"]["id_str"].as_str().unwrap().to_owned(), - twete_id: structure["target_object"]["id_str"].as_str().unwrap().to_owned() - })), - &"favorited_retweet" => Some(Box::new(Fav_RT { - user_id: structure["source"]["id_str"].as_str().unwrap().to_owned(), - twete_id: structure["target_object"]["id_str"].as_str().unwrap().to_owned() - })), - &"retweeted_retweet" => Some(Box::new(RT_RT { - user_id: structure["source"]["id_str"].as_str().unwrap().to_owned(), - twete_id: structure["target_object"]["id_str"].as_str().unwrap().to_owned() - })), -// &"blocked" => Blocked { }, -// &"unblocked" => Unblocked { }, -// &"quoted_tweet" => ???, - e => { println!("unrecognized event: {}", e); None } - } - } - } -} - impl User { pub fn from_json(json: serde_json::Value) -> Option { if let serde_json::Value::Object(json_map) = json { -- cgit v1.1