1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
//! This module contains the functions used only by the `queue-tweet` subsystem. //! //! The flow of the `queue-tweet` subsystem is as follows: //! //! ```plaintext //! Options::parse() //! |> ops::queue_tweet::tweets_path() //! |> ops::queue_tweet::get_tweet() //! |> ops::QueuedTweet::read() //! |> ops::QueuedTweet::write() //! ``` //! //! When queueing from file: //! //! ```plaintext //! Options::parse() //! |> ops::queue_tweet::tweets_path() //! |> ops::QueuedTweet::read() //! |> ops::QueuedTweet::read() //! |> ops::QueuedTweet::write() //! ``` use self::super::super::util::{prompt_any_len, prompt_nonzero_len, prompt_multiline, parse_relative_time}; use chrono::{ParseResult, FixedOffset, DateTime, Duration, Local}; use std::path::{PathBuf, Path}; use std::io::{BufRead, Write}; use self::super::QueuedTweet; /// Get the path to the file containing the global tweet queue. /// /// # Examples /// /// ``` /// # use tweetr::ops::queue_tweet; /// # use std::env::temp_dir; /// let tf = temp_dir().join("tweetr-doctest").join("ops-queue_tweets-tweets_path-0"); /// assert_eq!(queue_tweet::tweets_path(&tf), tf.join("tweets.toml")); /// ``` pub fn tweets_path(config_dir: &Path) -> PathBuf { config_dir.join("tweets.toml") } /// Prompt the user for application data. /// /// # Examples /// /// Queueing a tweet. /// /// ``` /// # extern crate tweetr; /// # extern crate chrono; /// # use tweetr::ops::{queue_tweet, QueuedTweet}; /// # use std::io::BufReader; /// # use chrono::DateTime; /// # fn main() { /// assert_eq!(queue_tweet::get_tweet(&mut BufReader::new(b"tweetr_test\n\ /// Test tweet\n\ /// 2016-09-09T00:33:30+02:00\n" as &[u8]), /// &mut Vec::new()), /// Some(QueuedTweet { /// author: "tweetr_test".to_string(), /// time: DateTime::parse_from_rfc3339("2016-09-09T00:33:30+02:00").unwrap(), /// content: "Test tweet".to_string(), /// time_posted: None, /// id: None, /// })); /// # } /// ``` /// /// Not queueing a tweet. /// /// ``` /// # use tweetr::ops::{queue_tweet, QueuedTweet}; /// # use std::io::BufReader; /// assert_eq!(queue_tweet::get_tweet(&mut BufReader::new(b"\n" as &[u8]), &mut Vec::new()), None); /// ``` pub fn get_tweet<R: BufRead, W: Write>(input: &mut R, output: &mut W) -> Option<QueuedTweet> { prompt_any_len(input, output, "Author (or empty to finish)", |_| true).unwrap().map(|uname| { let content = prompt_multiline(input, output, "Tweet content", |s| !s.trim().is_empty()).unwrap(); let time = prompt_nonzero_len(input, output, "Time to post the tweet (RFC2822, RFC3339 or relative)", |s| DateTime::parse_from_rfc2822(s).is_ok() || DateTime::parse_from_rfc3339(s).is_ok() || parse_relative_time(s).is_ok()) .unwrap(); writeln!(output, "").unwrap(); QueuedTweet { author: uname, time: DateTime::parse_from_rfc2822(&time) .or_else(|_| DateTime::parse_from_rfc3339(&time)) .or_else(|_| { let now = Local::now(); let now = now.with_timezone(now.offset()); Ok(now + Duration::from_std(parse_relative_time(&time).unwrap()).unwrap()) as ParseResult<DateTime<FixedOffset>> }) .unwrap(), content: content, time_posted: None, id: None, } }) }