about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/tweet.cpp43
-rw-r--r--src/tweet.h55
-rw-r--r--src/util.cpp37
-rw-r--r--src/util.h3
5 files changed, 99 insertions, 42 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 08851cf..7685af5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -21,7 +21,8 @@ add_library(twitter++
21 src/direct_message.cpp 21 src/direct_message.cpp
22 src/list.cpp 22 src/list.cpp
23 src/user.cpp 23 src/user.cpp
24 src/configuration.cpp) 24 src/configuration.cpp
25 src/util.cpp)
25 26
26set_property(TARGET twitter++ PROPERTY CXX_STANDARD 14) 27set_property(TARGET twitter++ PROPERTY CXX_STANDARD 14)
27set_property(TARGET twitter++ PROPERTY CXX_STANDARD_REQUIRED ON) 28set_property(TARGET twitter++ PROPERTY CXX_STANDARD_REQUIRED ON)
diff --git a/src/tweet.cpp b/src/tweet.cpp index 1c869f9..1003647 100644 --- a/src/tweet.cpp +++ b/src/tweet.cpp
@@ -1,11 +1,12 @@
1#include "tweet.h" 1#include "tweet.h"
2#include <json.hpp> 2#include <json.hpp>
3#include <sstream>
3#include "util.h" 4#include "util.h"
4#include "codes.h" 5#include "codes.h"
5#include "client.h" 6#include "client.h"
6 7
7namespace twitter { 8namespace twitter {
8 9
9 tweet::tweet(std::string data) try 10 tweet::tweet(std::string data) try
10 : _valid(true) 11 : _valid(true)
11 { 12 {
@@ -13,14 +14,20 @@ namespace twitter {
13 _id = json["id"].get<tweet_id>(); 14 _id = json["id"].get<tweet_id>();
14 _text = json["text"].get<std::string>(); 15 _text = json["text"].get<std::string>();
15 _author = std::make_unique<user>(json["user"].dump()); 16 _author = std::make_unique<user>(json["user"].dump());
16 17
18 std::tm ctt = { 0 };
19 std::stringstream createdAtStream;
20 createdAtStream << json["created_at"].get<std::string>();
21 createdAtStream >> std::get_time(&ctt, "%a %b %d %H:%M:%S +0000 %Y");
22 _created_at = twitter::timegm(&ctt);
23
17 if (!json["retweeted_status"].is_null()) 24 if (!json["retweeted_status"].is_null())
18 { 25 {
19 _is_retweet = true; 26 _is_retweet = true;
20 27
21 _retweeted_status = std::make_unique<tweet>(json["retweeted_status"].dump()); 28 _retweeted_status = std::make_unique<tweet>(json["retweeted_status"].dump());
22 } 29 }
23 30
24 if (!json["entities"].is_null()) 31 if (!json["entities"].is_null())
25 { 32 {
26 auto entities = json["entities"]; 33 auto entities = json["entities"];
@@ -39,7 +46,7 @@ namespace twitter {
39 { 46 {
40 std::throw_with_nested(malformed_object("tweet", data)); 47 std::throw_with_nested(malformed_object("tweet", data));
41 } 48 }
42 49
43 tweet::tweet(const tweet& other) 50 tweet::tweet(const tweet& other)
44 { 51 {
45 _valid = other._valid; 52 _valid = other._valid;
@@ -47,27 +54,27 @@ namespace twitter {
47 _text = other._text; 54 _text = other._text;
48 _author = std::make_unique<user>(*other._author); 55 _author = std::make_unique<user>(*other._author);
49 _is_retweet = other._is_retweet; 56 _is_retweet = other._is_retweet;
50 57
51 if (_is_retweet) 58 if (_is_retweet)
52 { 59 {
53 _retweeted_status = std::make_unique<tweet>(*other._retweeted_status); 60 _retweeted_status = std::make_unique<tweet>(*other._retweeted_status);
54 } 61 }
55 62
56 _mentions = other._mentions; 63 _mentions = other._mentions;
57 } 64 }
58 65
59 tweet::tweet(tweet&& other) : tweet() 66 tweet::tweet(tweet&& other) : tweet()
60 { 67 {
61 swap(*this, other); 68 swap(*this, other);
62 } 69 }
63 70
64 tweet& tweet::operator=(tweet other) 71 tweet& tweet::operator=(tweet other)
65 { 72 {
66 swap(*this, other); 73 swap(*this, other);
67 74
68 return *this; 75 return *this;
69 } 76 }
70 77
71 void swap(tweet& first, tweet& second) 78 void swap(tweet& first, tweet& second)
72 { 79 {
73 std::swap(first._valid, second._valid); 80 std::swap(first._valid, second._valid);
@@ -78,12 +85,12 @@ namespace twitter {
78 std::swap(first._retweeted_status, second._retweeted_status); 85 std::swap(first._retweeted_status, second._retweeted_status);
79 std::swap(first._mentions, second._mentions); 86 std::swap(first._mentions, second._mentions);
80 } 87 }
81 88
82 std::string tweet::generateReplyPrefill(const user& me) const 89 std::string tweet::generateReplyPrefill(const user& me) const
83 { 90 {
84 std::ostringstream output; 91 std::ostringstream output;
85 output << "@" << _author->getScreenName() << " "; 92 output << "@" << _author->getScreenName() << " ";
86 93
87 for (auto mention : _mentions) 94 for (auto mention : _mentions)
88 { 95 {
89 if ((mention.first != _author->getID()) && (mention.first != me.getID())) 96 if ((mention.first != _author->getID()) && (mention.first != me.getID()))
@@ -91,21 +98,21 @@ namespace twitter {
91 output << "@" << mention.second << " "; 98 output << "@" << mention.second << " ";
92 } 99 }
93 } 100 }
94 101
95 return output.str(); 102 return output.str();
96 } 103 }
97 104
98 std::string tweet::getURL() const 105 std::string tweet::getURL() const
99 { 106 {
100 assert(_valid); 107 assert(_valid);
101 108
102 std::ostringstream urlstr; 109 std::ostringstream urlstr;
103 urlstr << "https://twitter.com/"; 110 urlstr << "https://twitter.com/";
104 urlstr << _author->getScreenName(); 111 urlstr << _author->getScreenName();
105 urlstr << "/statuses/"; 112 urlstr << "/statuses/";
106 urlstr << _id; 113 urlstr << _id;
107 114
108 return urlstr.str(); 115 return urlstr.str();
109 } 116 }
110 117
111}; 118};
diff --git a/src/tweet.h b/src/tweet.h index ae1c916..71a27bd 100644 --- a/src/tweet.h +++ b/src/tweet.h
@@ -7,84 +7,93 @@
7#include <cassert> 7#include <cassert>
8#include <list> 8#include <list>
9#include <memory> 9#include <memory>
10#include <ctime>
10#include "user.h" 11#include "user.h"
11 12
12namespace twitter { 13namespace twitter {
13 14
14 class client; 15 class client;
15 16
16 typedef unsigned long long tweet_id; 17 typedef unsigned long long tweet_id;
17 18
18 class tweet { 19 class tweet {
19 public: 20 public:
20 21
21 tweet() {} 22 tweet() {}
22 tweet(std::string data); 23 tweet(std::string data);
23 24
24 tweet(const tweet& other); 25 tweet(const tweet& other);
25 tweet(tweet&& other); 26 tweet(tweet&& other);
26 27
27 tweet& operator=(tweet other); 28 tweet& operator=(tweet other);
28 29
29 friend void swap(tweet& first, tweet& second); 30 friend void swap(tweet& first, tweet& second);
30 31
31 tweet_id getID() const 32 tweet_id getID() const
32 { 33 {
33 assert(_valid); 34 assert(_valid);
34 35
35 return _id; 36 return _id;
36 } 37 }
37 38
38 std::string getText() const 39 std::string getText() const
39 { 40 {
40 assert(_valid); 41 assert(_valid);
41 42
42 return _text; 43 return _text;
43 } 44 }
44 45
45 const user& getAuthor() const 46 const user& getAuthor() const
46 { 47 {
47 assert(_valid); 48 assert(_valid);
48 49
49 return *_author; 50 return *_author;
50 } 51 }
51 52
53 const std::time_t& getCreatedAt() const
54 {
55 assert(_valid);
56
57 return _created_at;
58 }
59
52 bool isRetweet() const 60 bool isRetweet() const
53 { 61 {
54 assert(_valid); 62 assert(_valid);
55 63
56 return _is_retweet; 64 return _is_retweet;
57 } 65 }
58 66
59 const tweet& getRetweet() const 67 const tweet& getRetweet() const
60 { 68 {
61 assert(_valid && _is_retweet); 69 assert(_valid && _is_retweet);
62 70
63 return *_retweeted_status; 71 return *_retweeted_status;
64 } 72 }
65 73
66 const std::vector<std::pair<user_id, std::string>>& getMentions() const 74 const std::vector<std::pair<user_id, std::string>>& getMentions() const
67 { 75 {
68 assert(_valid); 76 assert(_valid);
69 77
70 return _mentions; 78 return _mentions;
71 } 79 }
72 80
73 std::string generateReplyPrefill(const user& me) const; 81 std::string generateReplyPrefill(const user& me) const;
74 82
75 std::string getURL() const; 83 std::string getURL() const;
76 84
77 private: 85 private:
78 86
79 bool _valid = false; 87 bool _valid = false;
80 tweet_id _id; 88 tweet_id _id;
81 std::string _text; 89 std::string _text;
82 std::unique_ptr<user> _author; 90 std::unique_ptr<user> _author;
91 std::time_t _created_at;
83 bool _is_retweet = false; 92 bool _is_retweet = false;
84 std::unique_ptr<tweet> _retweeted_status; 93 std::unique_ptr<tweet> _retweeted_status;
85 std::vector<std::pair<user_id, std::string>> _mentions; 94 std::vector<std::pair<user_id, std::string>> _mentions;
86 }; 95 };
87 96
88}; 97};
89 98
90#endif /* end of include guard: TWEET_H_CE980721 */ 99#endif /* end of include guard: TWEET_H_CE980721 */
diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000..5952138 --- /dev/null +++ b/src/util.cpp
@@ -0,0 +1,37 @@
1#include "util.h"
2
3namespace twitter {
4
5 // Eric S Raymond wrote this
6 /* struct tm to seconds since Unix epoch */
7 time_t timegm(struct tm * t)
8 {
9 long year;
10 time_t result;
11 #define MONTHSPERYEAR 12 /* months per calendar year */
12 static const int cumdays[MONTHSPERYEAR] =
13 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
14
15 /*@ +matchanyintegral @*/
16 year = 1900 + t->tm_year + t->tm_mon / MONTHSPERYEAR;
17 result = (year - 1970) * 365 + cumdays[t->tm_mon % MONTHSPERYEAR];
18 result += (year - 1968) / 4;
19 result -= (year - 1900) / 100;
20 result += (year - 1600) / 400;
21 if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) &&
22 (t->tm_mon % MONTHSPERYEAR) < 2)
23 result--;
24 result += t->tm_mday - 1;
25 result *= 24;
26 result += t->tm_hour;
27 result *= 60;
28 result += t->tm_min;
29 result *= 60;
30 result += t->tm_sec;
31 if (t->tm_isdst == 1)
32 result -= 3600;
33 /*@ -matchanyintegral @*/
34 return (result);
35 }
36
37}
diff --git a/src/util.h b/src/util.h index 8cbe054..b950728 100644 --- a/src/util.h +++ b/src/util.h
@@ -4,6 +4,7 @@
4#include <string> 4#include <string>
5#include <sstream> 5#include <sstream>
6#include <memory> 6#include <memory>
7#include <ctime>
7 8
8namespace twitter { 9namespace twitter {
9 10
@@ -25,6 +26,8 @@ namespace twitter {
25 return result.str(); 26 return result.str();
26 } 27 }
27 28
29 time_t timegm(struct tm * t);
30
28}; 31};
29 32
30#endif /* end of include guard: UTIL_H_440DEAA0 */ 33#endif /* end of include guard: UTIL_H_440DEAA0 */