aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wortman <ixineeringeverywhere@gmail.com>2017-11-30 03:07:05 -0800
committerAndy Wortman <ixineeringeverywhere@gmail.com>2017-11-30 03:07:05 -0800
commit3c042afe7872d5488fd91c2b1a42036953f604eb (patch)
tree99a5d9f19b3031e068a3ce833ea59656b484a3e7
parent4681214e63fad92850b62335fb32c11fde51e94f (diff)
remove unneeded params, adjust id display
tweets are now recorded with the date they are recieved at dated id lookup is now supported tweet ids, where displayed, are displayed in a convenient form: if the tweet was recieved today, show the today id if the tweet was recieved on a different day, show the bare id many instances where display_info was passed for logging information, the parameter has become unnecessary, so it's gone now
-rw-r--r--Cargo.toml2
-rw-r--r--src/commands/fav.rs4
-rw-r--r--src/commands/thread.rs2
-rw-r--r--src/commands/twete.rs14
-rw-r--r--src/commands/view.rs2
-rw-r--r--src/display/mod.rs28
-rw-r--r--src/main.rs1
-rw-r--r--src/tw/mod.rs200
-rw-r--r--src/tw/tweet.rs5
9 files changed, 180 insertions, 78 deletions
diff --git a/Cargo.toml b/Cargo.toml
index b37cf52..b1f3677 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -26,6 +26,6 @@ hyper-tls = "*"
"futures" = "*"
"serde_json" = "*"
"chan" = "*"
-chrono = "0.4"
+chrono = { version = "0.4", features = ["serde"] }
serde = "*"
serde_derive = "*"
diff --git a/src/commands/fav.rs b/src/commands/fav.rs
index 0bee8ce..5e5f2a2 100644
--- a/src/commands/fav.rs
+++ b/src/commands/fav.rs
@@ -21,7 +21,7 @@ fn unfav(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, di
let maybe_id = TweetId::parse(line.to_owned());
match maybe_id {
Ok(twid) => {
- if let Some(twete) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self
+ if let Some(twete) = tweeter.retrieve_tweet(&twid).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())
@@ -53,7 +53,7 @@ fn fav(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, disp
match maybe_id {
Ok(twid) => {
// tweeter.to_twitter_tweet_id(twid)...
- if let Some(twete) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self
+ if let Some(twete) = tweeter.retrieve_tweet(&twid).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())
diff --git a/src/commands/thread.rs b/src/commands/thread.rs
index 302e641..f82fb13 100644
--- a/src/commands/thread.rs
+++ b/src/commands/thread.rs
@@ -38,7 +38,7 @@ 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, display_info).map(|x| x.clone()) {
+ if let Some(twete) = tweeter.retrieve_tweet(&twid).map(|x| x.clone()) {
tweeter.set_thread(name.to_string(), twete.internal_id);
display_info.status(format!("Ok! Recorded {:?} as thread {}", twid, name));
} else {
diff --git a/src/commands/twete.rs b/src/commands/twete.rs
index ac4bbeb..ebf3c3d 100644
--- a/src/commands/twete.rs
+++ b/src/commands/twete.rs
@@ -22,7 +22,7 @@ fn del(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, disp
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, display_info).map(|x| x.id.to_owned()) {
+ if let Some(twitter_id) = tweeter.retrieve_tweet(&twid).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())
@@ -100,7 +100,7 @@ fn thread(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, d
let maybe_id = TweetId::parse(id_str.to_owned());
match maybe_id {
Ok(twid) => {
- if let Some(twete) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self
+ if let Some(twete) = tweeter.retrieve_tweet(&twid).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 {
@@ -152,13 +152,13 @@ fn rep(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, disp
let maybe_id = TweetId::parse(id_str.to_owned());
match maybe_id {
Ok(twid) => {
- if let Some(twete) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self
+ if let Some(twete) = tweeter.retrieve_tweet(&twid).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<String> = 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), display_info)).map(|x| x.clone()) {
+ if let Some(rt_tweet) = twete.rt_tweet.and_then(|id| tweeter.retrieve_tweet(&TweetId::Twitter(id))).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);
@@ -191,7 +191,7 @@ fn rep(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, disp
}
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
+ if let Some(twete) = tweeter.retrieve_tweet(&twid).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) => {
@@ -226,7 +226,7 @@ fn quote(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer, di
let maybe_id = TweetId::parse(id_str.to_owned());
match maybe_id {
Ok(twid) => {
- if let Some(twete) = tweeter.retrieve_tweet(&twid, display_info).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self
+ if let Some(twete) = tweeter.retrieve_tweet(&twid).map(|x| x.clone()) { // TODO: no clone when this stops taking &mut self
let substituted = ::url_encode(reply);
let attachment_url = ::url_encode(
&format!(
@@ -281,7 +281,7 @@ fn retwete(line: String, tweeter: &mut tw::TwitterCache, queryer: &mut Queryer,
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, display_info).map(|x| x.id.to_owned()) {
+ if let Some(twitter_id) = tweeter.retrieve_tweet(&twid).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)
diff --git a/src/commands/view.rs b/src/commands/view.rs
index 41dd9b3..18ba871 100644
--- a/src/commands/view.rs
+++ b/src/commands/view.rs
@@ -19,7 +19,7 @@ pub static VIEW: Command = Command {
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, display_info) {
+ if let Some(twete) = tweeter.retrieve_tweet(&twid) {
display_info.recv(display::Infos::TweetWithContext(
TweetId::Twitter(twete.id.to_owned()),
format!("link: https://twitter.com/i/web/status/{}", twete.id)
diff --git a/src/display/mod.rs b/src/display/mod.rs
index 3e9d725..8d1f725 100644
--- a/src/display/mod.rs
+++ b/src/display/mod.rs
@@ -345,9 +345,10 @@ pub fn paint(tweeter: &::tw::TwitterCache, display_info: &mut DisplayInfo) -> Re
// draw input prompt
let mut i = 0;
let log_size = 4;
- let last_elem = display_info.log.len().saturating_sub(log_size);
+ let last_tail_log = display_info.log.len().saturating_sub(display_info.infos_seek as usize);
+ let first_tail_log = last_tail_log.saturating_sub(log_size);
{
- let to_show = display_info.log[last_elem..].iter().rev();
+ let to_show = display_info.log[first_tail_log..last_tail_log].iter().rev();
for line in to_show {
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;
@@ -435,7 +436,7 @@ pub fn paint(tweeter: &::tw::TwitterCache, display_info: &mut DisplayInfo) -> Re
let wrapped = if total_length <= 1024 {
into_display_lines(pre_split, width)
} else {
- vec!["This tweet discarded for your convenience".to_owned()]
+ vec![format!("This tweet discarded for your convenience: (id: {})", id)]
};
wrapped.into_iter().rev().collect()
}
@@ -551,7 +552,7 @@ impl Render for tw::events::Event {
}
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()), display_info).map(|x| x.clone()) {
+ if let Some(_tweet) = tweeter.retrieve_tweet(&TweetId::Twitter(twete_id.to_owned())).map(|x| x.clone()) {
result.push(format!("-------------DELETED------------------"));
result.extend(render_twete(&TweetId::Twitter(twete_id), tweeter, display_info, Some(width)));
result.push(format!("-------------DELETED------------------"));
@@ -621,7 +622,7 @@ fn pad_lines(lines: Vec<String>, padding: &str) -> Vec<String> {
pub fn render_twete(twete_id: &TweetId, tweeter: &tw::TwitterCache, display_info: &mut DisplayInfo, width: Option<u16>) -> Vec<String> {
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()) {
+ match tweeter.retrieve_tweet(twete_id).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, display_info, width.map(|x| x - 4)), " "));
@@ -636,7 +637,7 @@ pub fn render_twete_no_recurse(twete_id: &TweetId, tweeter: &tw::TwitterCache, d
// ~~ 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, display_info).map(|x| x.clone()) {
+ match tweeter.retrieve_tweet(twete_id).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();
@@ -657,27 +658,26 @@ pub fn render_twete_no_recurse(twete_id: &TweetId, tweeter: &tw::TwitterCache, d
.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, display_info).unwrap().clone();
+ let tweet = tweeter.retrieve_tweet(&tweet_id).unwrap().clone();
+ let tweet_id = tweeter.display_id_for_tweet(&tweet);
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
// of the retweeter tweet if it's there
- let mut id_string = format!("{}id {}", id_color, tweet.internal_id);
+ let mut id_string = format!("{}id {}", id_color, tweet_id);
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()), display_info) {
- Some(reply_tweet) => TweetId::Bare(reply_tweet.internal_id),
- None => TweetId::Twitter(reply_id)
- };
+ let reply_tweet_id = tweeter.display_id_for_tweet_id(&TweetId::Twitter(reply_id.to_owned()));
id_string.push_str(&format!(" reply to {}", reply_tweet_id))
}
if let Some(rt_id) = maybe_rt_id {
- let rt = tweeter.retrieve_tweet(&rt_id, display_info).unwrap().clone();
+ let rt = tweeter.retrieve_tweet(&rt_id).unwrap().clone();
+ let rt_id = tweeter.display_id_for_tweet(&rt);
let rt_author = tweeter.retrieve_user(&rt.author_id).unwrap().clone();
- id_string.push_str(&format!(" (rt id {})", rt.internal_id));
+ id_string.push_str(&format!(" (rt id {})", rt_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 73ad9d9..d8ef738 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,7 @@
#![feature(vec_remove_item)]
extern crate serde_json;
+extern crate chrono;
extern crate termion;
extern crate termios;
diff --git a/src/tw/mod.rs b/src/tw/mod.rs
index 629a6c7..737286d 100644
--- a/src/tw/mod.rs
+++ b/src/tw/mod.rs
@@ -131,17 +131,21 @@ pub struct TwitterCache {
// twitter::num // twiter tweet id num
struct IdConversions {
// maps a day to the base id for tweets off that day.
- id_per_date: HashMap<String, u64>,
- id_to_tweet_id: HashMap<u64, String>
+ id_to_tweet_id: HashMap<u64, String>,
// twitter id to id is satisfied by looking up the twitter id in tweeter.tweets and getting
// .inner_id
+ // YYYYMMDD : day_id : inner_tweet_id
+ tweets_by_date: HashMap<String, HashMap<u64, u64>>,
+ // YYYYMMDD : inner_tweet_id : day_id
+ tweets_by_date_and_tweet_id: HashMap<String, HashMap<u64, u64>>
}
impl Default for IdConversions {
fn default() -> Self {
IdConversions {
- id_per_date: HashMap::new(),
- id_to_tweet_id: HashMap::new()
+ id_to_tweet_id: HashMap::new(),
+ tweets_by_date: HashMap::new(),
+ tweets_by_date_and_tweet_id: HashMap::new()
}
}
}
@@ -180,6 +184,7 @@ mod tests {
fn tweet_id_parse_test() {
assert_eq!(TweetId::parse("12345".to_string()), Ok(TweetId::Today(12345)));
assert_eq!(TweetId::parse("20170403:12345".to_string()), Ok(TweetId::Dated("20170403".to_string(), 12345)));
+ assert_eq!(TweetId::parse("20170403:12345".to_string()), Ok(TweetId::Dated("20170403".to_string(), 12345)));
assert_eq!(TweetId::parse(":12345".to_string()), Ok(TweetId::Bare(12345)));
assert_eq!(TweetId::parse("twitter:12345".to_string()), Ok(TweetId::Twitter("12345".to_string())));
assert_eq!(TweetId::parse("twitter:asdf".to_string()), Ok(TweetId::Twitter("asdf".to_string())));
@@ -192,6 +197,57 @@ mod tests {
assert_eq!(TweetId::parse(":a34".to_string()), Err("invalid digit found in string".to_owned()));
assert_eq!(TweetId::parse("asdf:34".to_string()), Err("Unrecognized id string: asdf:34".to_owned()));
}
+
+ #[test]
+ fn test_tweet_retrieval() {
+ let today = Local::now();
+ let yesterday = today - chrono::Duration::days(1);
+ let tweets = vec![
+ Tweet {
+ id: "manual_tweet_1".to_owned(),
+ author_id: "author_1".to_owned(),
+ text: "this is a test".to_owned(),
+ created_at: "1234 not real lol".to_owned(),
+ recieved_at: yesterday,
+ urls: HashMap::new(),
+ quoted_tweet_id: None,
+ rt_tweet: None,
+ reply_to_tweet: None,
+ internal_id: 0
+ },
+ Tweet {
+ id: "manual_tweet_2".to_owned(),
+ author_id: "author_1".to_owned(),
+ text: "this is a test".to_owned(),
+ created_at: "1234 not real lol".to_owned(),
+ recieved_at: today,
+ urls: HashMap::new(),
+ quoted_tweet_id: None,
+ rt_tweet: None,
+ reply_to_tweet: None,
+ internal_id: 0
+ }
+ ];
+
+ let mut tweeter = TwitterCache::new();
+
+ for tweet in &tweets {
+ tweeter.number_and_insert_tweet(tweet.to_owned());
+ }
+
+ assert_eq!(
+ tweeter.retrieve_tweet(&TweetId::Twitter("manual_tweet_1".to_owned())).map(|x| x.id.to_owned()),
+ Some(tweets[0].clone()).map(|x| x.id)
+ );
+ assert_eq!(
+ tweeter.retrieve_tweet(&TweetId::Today(0)).map(|x| x.id.to_owned()),
+ Some(tweets[1].clone()).map(|x| x.id)
+ );
+ assert_eq!(
+ tweeter.retrieve_tweet(&TweetId::Dated(format!("{:04}{:02}{:02}", yesterday.year(), yesterday.month(), yesterday.day()), 0)).map(|x| x.id.to_owned()),
+ Some(tweets[0].clone()).map(|x| x.id)
+ );
+ }
}
impl TweetId {
@@ -230,18 +286,55 @@ impl IdConversions {
//
// except in the TweetId::Twitter case we TweetId -> Option<Tweet> -> Option<u64> ... to ->
// Option<Tweet> in the future?
- fn to_inner_id(&self, tweeter: &TwitterCache, twid: TweetId, display_info: &mut DisplayInfo) -> Option<u64> {
+ fn to_twitter_id(&self, twid: TweetId) -> Option<String> {
match twid {
TweetId::Today(num) => {
- let first_for_today: u64 = 0;
- Some(first_for_today + num)
+ let now = Local::now();
+ let now_date_str = format!("{:04}{:02}{:02}", now.year(), now.month(), now.day());
+ let tweet_id = self.tweets_by_date.get(&now_date_str).and_then(|x| x.get(&num));
+ tweet_id.and_then(|x| self.id_to_tweet_id.get(x)).map(|x| x.to_owned())
},
TweetId::Dated(date, num) => {
- let first_for_date: u64 = 0;
- Some(first_for_date + num)
+ let tweet_id = self.tweets_by_date.get(&date).and_then(|x| x.get(&num));
+ tweet_id.and_then(|x| self.id_to_tweet_id.get(x)).map(|x| x.to_owned())
},
- TweetId::Bare(num) => Some(num),
- twid @ TweetId::Twitter(_) => tweeter.retrieve_tweet(&twid, display_info).map(|x| x.internal_id)
+ TweetId::Bare(num) => self.id_to_tweet_id.get(&num).map(|x| x.to_owned()),
+ TweetId::Twitter(id) => Some(id)
+ }
+ }
+
+ fn to_display_id(&self, twid: &TweetId, tweeter: &TwitterCache) -> TweetId {
+ match twid {
+ id @ &TweetId::Today(_) => id.to_owned(),
+ id @ &TweetId::Dated(_, _) => {
+ tweeter.retrieve_tweet(id).map(|x| TweetId::Bare(x.internal_id)).unwrap_or(id.to_owned())
+ },
+ id @ &TweetId::Bare(_) => {
+ tweeter.retrieve_tweet(id).and_then(|tweet| {
+ let now = Local::now();
+ let tweet_date = tweet.recieved_at.with_timezone(&now.timezone());
+ if now.year() == tweet_date.year() && now.month() == tweet_date.month() && now.day() == tweet_date.day() {
+ let date_string = format!("{:04}{:02}{:02}", tweet.recieved_at.year(), tweet.recieved_at.month(), tweet.recieved_at.day());
+ let today_id = self.tweets_by_date_and_tweet_id.get(&date_string).and_then(|m| m.get(&tweet.internal_id));
+ today_id.map(|x| TweetId::Today(*x))
+ } else {
+ None
+ }
+ }).unwrap_or(id.to_owned())
+ },
+ id @ &TweetId::Twitter(_) => {
+ tweeter.retrieve_tweet(id).and_then(|tweet| {
+ let now = Local::now();
+ let tweet_date = tweet.recieved_at.with_timezone(&now.timezone());
+ if now.year() == tweet_date.year() && now.month() == tweet_date.month() && now.day() == tweet_date.day() {
+ let date_string = format!("{:04}{:02}{:02}", tweet.recieved_at.year(), tweet.recieved_at.month(), tweet.recieved_at.day());
+ let today_id = self.tweets_by_date_and_tweet_id.get(&date_string).and_then(|m| m.get(&tweet.internal_id));
+ today_id.map(|x| TweetId::Today(*x))
+ } else {
+ None
+ }
+ }).unwrap_or(id.to_owned())
+ }
}
}
}
@@ -500,10 +593,44 @@ impl TwitterCache {
if tw.internal_id == 0 {
tw.internal_id = (self.tweets.len() as u64) + 1;
self.id_conversions.id_to_tweet_id.insert(tw.internal_id, tw.id.to_owned());
+ let local_recv_time = tw.recieved_at.with_timezone(&Local::now().timezone());
+ let tweet_date = format!("{:04}{:02}{:02}", local_recv_time.year(), local_recv_time.month(), local_recv_time.day());
+ if !self.id_conversions.tweets_by_date.contains_key(&tweet_date) {
+ self.id_conversions.tweets_by_date.insert(tweet_date.clone(), HashMap::new());
+ }
+ if !self.id_conversions.tweets_by_date_and_tweet_id.contains_key(&tweet_date) {
+ self.id_conversions.tweets_by_date_and_tweet_id.insert(tweet_date.clone(), HashMap::new());
+ }
+
+ let date_map: &mut HashMap<u64, u64> = self.id_conversions.tweets_by_date.get_mut(&tweet_date).unwrap();
+ let next_idx = date_map.len() as u64;
+ date_map.insert(next_idx, tw.internal_id);
+
+ let date_map: &mut HashMap<u64, u64> = self.id_conversions.tweets_by_date_and_tweet_id.get_mut(&tweet_date).unwrap();
+ let next_idx = date_map.len() as u64;
+ date_map.insert(tw.internal_id, next_idx);
+
self.tweets.insert(tw.id.to_owned(), tw);
}
}
}
+ pub fn display_id_for_tweet(&self, tweet: &Tweet) -> TweetId {
+ let now = Local::now();
+ let tweet_date = tweet.recieved_at.with_timezone(&now.timezone());
+ let bare_id = TweetId::Bare(tweet.internal_id);
+ let maybe_dated_id = if now.year() == tweet_date.year() && now.month() == tweet_date.month() && now.day() == tweet_date.day() {
+ let date_string = format!("{:04}{:02}{:02}", tweet.recieved_at.year(), tweet.recieved_at.month(), tweet.recieved_at.day());
+ let today_id = self.id_conversions.tweets_by_date_and_tweet_id.get(&date_string).and_then(|m| m.get(&tweet.internal_id));
+ today_id.map(|x| TweetId::Today(*x))
+ } else {
+ None
+ };
+
+ maybe_dated_id.unwrap_or(bare_id)
+ }
+ pub fn display_id_for_tweet_id(&self, twid: &TweetId) -> TweetId {
+ self.id_conversions.to_display_id(twid, self)
+ }
pub fn load_cache(display_info: &mut DisplayInfo) -> TwitterCache {
if Path::new(TwitterCache::PROFILE_CACHE).is_file() {
let mut buf = vec![];
@@ -641,54 +768,23 @@ impl TwitterCache {
/* nothing else to care about now, i think? */
}
}
- 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);
- match maybe_tweet_id {
- Some(id) => self.tweets.get(id),
- None => None
- }
- },
- &TweetId::Today(ref id) => {
- let inner_id = self.id_conversions.id_to_tweet_id.get(id);
- display_info.status("Retrieving tweets with dated IDs is not yet supported.".to_string());
- None
- },
- &TweetId::Dated(ref date, ref id) => {
- display_info.status("Retrieving tweets with dated IDs is not yet supported.".to_string());
- None
- },
- &TweetId::Twitter(ref id) => self.tweets.get(id)
- }
+ pub fn retrieve_tweet(&self, tweet_id: &TweetId) -> Option<&Tweet> {
+ let maybe_tweet_id = self.id_conversions.to_twitter_id(tweet_id.to_owned());
+ maybe_tweet_id.and_then(|id| self.tweets.get(&id))
}
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, 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, display_info)
- }
- &TweetId::Today(ref id) => {
- // we can do nothing but just try to get it
- 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, 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) => display_info.status(format!("Unable to retrieve tweet {}:\n{}", id, e))
- };
- }
- self.retrieve_tweet(tweet_id, display_info)
+ if let &TweetId::Twitter(ref id) = tweet_id {
+ if !self.tweets.contains_key(id) {
+ match self.look_up_tweet(id, &mut queryer) {
+ Ok(json) => self.cache_api_tweet(json),
+ Err(e) => display_info.status(format!("Unable to retrieve tweet {}:\n{}", id, e))
+ };
}
}
+ self.retrieve_tweet(tweet_id)
}
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) {
diff --git a/src/tw/tweet.rs b/src/tw/tweet.rs
index 38b838d..2ca32c3 100644
--- a/src/tw/tweet.rs
+++ b/src/tw/tweet.rs
@@ -1,5 +1,7 @@
extern crate serde_json;
+use chrono::prelude::*;
+
use std::collections::HashMap;
use tw::user::User;
@@ -10,6 +12,8 @@ pub struct Tweet {
pub author_id: String,
pub text: String,
pub created_at: String, // lol
+ #[serde(default = "Utc::now")]
+ pub recieved_at: DateTime<Utc>,
#[serde(skip_serializing_if="HashMap::is_empty")]
#[serde(default = "HashMap::default")]
pub urls: HashMap<String, String>,
@@ -84,6 +88,7 @@ impl Tweet {
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())