extern crate serde_json; use chrono::prelude::*; use std::collections::HashMap; use tw::user::User; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Tweet { pub id: String, pub author_id: String, pub text: String, pub created_at: String, // lol #[serde(default = "Utc::now")] pub recieved_at: DateTime, #[serde(skip_serializing_if="HashMap::is_empty")] #[serde(default = "HashMap::default")] pub urls: HashMap, #[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_serializing_if="Option::is_none")] #[serde(default = "Option::default")] pub reply_to_tweet: Option, #[serde(skip)] pub internal_id: u64 } impl Tweet { pub fn get_mentions(&self) -> Vec { self.text.split(&[ ',', '.', '/', ';', '\'', '[', ']', '\\', '~', '!', '#', '$', '%', '^', '&', '*', '(', ')', '-', '=', '{', '}', '|', ':', '"', '<', '>', '?', '`', ' ' // forgot this initially. awkward. ][..]) .filter(|x| x.starts_with("@") && x.len() > 1 && x.chars().skip(1).all(|c| c != '@')) // discard @, mentions are just the usernames. .map(|handle| handle.chars().skip(1).collect()) .collect() } pub fn from_api_json(json: serde_json::Value) -> Result<(Tweet, User), String> { Tweet::from_json(json.clone()).and_then(|tw| { 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) -> Result { if let serde_json::Value::Object(json_map) = json { let mut url_map: HashMap = HashMap::new(); for entry in json_map["entities"]["urls"].as_array().unwrap() { url_map.insert(entry["url"].as_str().unwrap().to_owned(), entry["expanded_url"].as_str().unwrap().to_owned()); } 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()); let reply_to_tweet = json_map.get("in_reply_to_status_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 Ok(Tweet { id: id_str.to_owned(), author_id: author_id.to_owned(), text: text, created_at: created_at.to_owned(), recieved_at: Utc::now(), urls: url_map, 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, reply_to_tweet: reply_to_tweet, internal_id: 0 }) } } } Err("Invalid tweet json".to_owned()) } }