diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-08-05 15:58:14 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-08-05 15:58:14 -0400 |
commit | b7bb942cadfe3d657895af1557b78acc2559947e (patch) | |
tree | 66ec390ba1b30c4d3012c3ec3526f9489c41d8f9 /src | |
parent | 204181c5654cee745b6b1ba98675609e784f0ee1 (diff) | |
download | libtwittercpp-b7bb942cadfe3d657895af1557b78acc2559947e.tar.gz libtwittercpp-b7bb942cadfe3d657895af1557b78acc2559947e.tar.bz2 libtwittercpp-b7bb942cadfe3d657895af1557b78acc2559947e.zip |
Tweets store their created time
C/C++ time handling is awful, pass it on
Diffstat (limited to 'src')
-rw-r--r-- | src/tweet.cpp | 43 | ||||
-rw-r--r-- | src/tweet.h | 55 | ||||
-rw-r--r-- | src/util.cpp | 37 | ||||
-rw-r--r-- | src/util.h | 3 |
4 files changed, 97 insertions, 41 deletions
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 | ||
7 | namespace twitter { | 8 | namespace 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 | ||
12 | namespace twitter { | 13 | namespace 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 | |||
3 | namespace 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 | ||
8 | namespace twitter { | 9 | namespace 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 */ |