diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/auth.cpp | 2 | ||||
| -rw-r--r-- | src/client.cpp | 311 | ||||
| -rw-r--r-- | src/client.h | 15 | ||||
| -rw-r--r-- | src/codes.cpp | 24 | ||||
| -rw-r--r-- | src/codes.h | 31 | ||||
| -rw-r--r-- | src/tweet.cpp | 2 | ||||
| -rw-r--r-- | src/tweet.h | 4 | ||||
| -rw-r--r-- | src/twitter.h | 24 | ||||
| -rw-r--r-- | src/util.h | 29 |
9 files changed, 402 insertions, 40 deletions
| diff --git a/src/auth.cpp b/src/auth.cpp index 325c521..f0f17e0 100644 --- a/src/auth.cpp +++ b/src/auth.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | #include "twitter.h" | 1 | #include "auth.h" |
| 2 | 2 | ||
| 3 | namespace twitter { | 3 | namespace twitter { |
| 4 | 4 | ||
| diff --git a/src/client.cpp b/src/client.cpp index b71ff70..39d6b5d 100644 --- a/src/client.cpp +++ b/src/client.cpp | |||
| @@ -1,10 +1,81 @@ | |||
| 1 | #include "client.h" | 1 | #include "client.h" |
| 2 | #include <curl_easy.h> | ||
| 3 | #include <curl_header.h> | ||
| 4 | #include <sstream> | 2 | #include <sstream> |
| 5 | #include <set> | 3 | #include <set> |
| 6 | #include <algorithm> | 4 | #include <algorithm> |
| 7 | #include <liboauthcpp/liboauthcpp.h> | 5 | #include <liboauthcpp/liboauthcpp.h> |
| 6 | #include "util.h" | ||
| 7 | |||
| 8 | // These are here for debugging curl stuff | ||
| 9 | |||
| 10 | static | ||
| 11 | void dump(const char *text, | ||
| 12 | FILE *stream, unsigned char *ptr, size_t size) | ||
| 13 | { | ||
| 14 | size_t i; | ||
| 15 | size_t c; | ||
| 16 | unsigned int width=80; | ||
| 17 | |||
| 18 | fprintf(stream, "%s, %10.10ld bytes (0x%8.8lx)\n", | ||
| 19 | text, (long)size, (long)size); | ||
| 20 | |||
| 21 | for(i=0; i<size; i+= width) { | ||
| 22 | fprintf(stream, "%4.4lx: ", (long)i); | ||
| 23 | |||
| 24 | /* show hex to the left | ||
| 25 | for(c = 0; c < width; c++) { | ||
| 26 | if(i+c < size) | ||
| 27 | fprintf(stream, "%02x ", ptr[i+c]); | ||
| 28 | else | ||
| 29 | fputs(" ", stream); | ||
| 30 | }*/ | ||
| 31 | |||
| 32 | /* show data on the right */ | ||
| 33 | for(c = 0; (c < width) && (i+c < size); c++) { | ||
| 34 | char x = (ptr[i+c] >= 0x20 && ptr[i+c] < 0x80) ? ptr[i+c] : '.'; | ||
| 35 | fputc(x, stream); | ||
| 36 | } | ||
| 37 | |||
| 38 | fputc('\n', stream); /* newline */ | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | static | ||
| 43 | int my_trace(CURL *handle, curl_infotype type, | ||
| 44 | char *data, size_t size, | ||
| 45 | void *userp) | ||
| 46 | { | ||
| 47 | const char *text; | ||
| 48 | (void)handle; /* prevent compiler warning */ | ||
| 49 | |||
| 50 | switch (type) { | ||
| 51 | case CURLINFO_TEXT: | ||
| 52 | fprintf(stderr, "== Info: %s", data); | ||
| 53 | default: /* in case a new one is introduced to shock us */ | ||
| 54 | return 0; | ||
| 55 | |||
| 56 | case CURLINFO_HEADER_OUT: | ||
| 57 | text = "=> Send header"; | ||
| 58 | break; | ||
| 59 | case CURLINFO_DATA_OUT: | ||
| 60 | text = "=> Send data"; | ||
| 61 | break; | ||
| 62 | case CURLINFO_SSL_DATA_OUT: | ||
| 63 | text = "=> Send SSL data"; | ||
| 64 | break; | ||
| 65 | case CURLINFO_HEADER_IN: | ||
| 66 | text = "<= Recv header"; | ||
| 67 | break; | ||
| 68 | case CURLINFO_DATA_IN: | ||
| 69 | text = "<= Recv data"; | ||
| 70 | break; | ||
| 71 | case CURLINFO_SSL_DATA_IN: | ||
| 72 | text = "<= Recv SSL data"; | ||
| 73 | break; | ||
| 74 | } | ||
| 75 | |||
| 76 | dump(text, stderr, (unsigned char *)data, size); | ||
| 77 | return 0; | ||
| 78 | } | ||
| 8 | 79 | ||
| 9 | namespace twitter { | 80 | namespace twitter { |
| 10 | 81 | ||
| @@ -22,18 +93,181 @@ namespace twitter { | |||
| 22 | delete _oauth_consumer; | 93 | delete _oauth_consumer; |
| 23 | } | 94 | } |
| 24 | 95 | ||
| 25 | response client::updateStatus(std::string msg, tweet& result) | 96 | response client::updateStatus(std::string msg, tweet& result, std::list<long> media_ids) |
| 26 | { | 97 | { |
| 27 | std::ostringstream output; | ||
| 28 | curl::curl_ios<std::ostringstream> ios(output); | ||
| 29 | curl::curl_easy conn(ios); | ||
| 30 | |||
| 31 | std::stringstream datastrstream; | 98 | std::stringstream datastrstream; |
| 32 | datastrstream << "status=" << OAuth::PercentEncode(msg); | 99 | datastrstream << "status=" << OAuth::PercentEncode(msg); |
| 33 | 100 | ||
| 101 | if (!media_ids.empty()) | ||
| 102 | { | ||
| 103 | datastrstream << "&media_ids="; | ||
| 104 | datastrstream << twitter::implode(std::begin(media_ids), std::end(media_ids), ","); | ||
| 105 | } | ||
| 106 | |||
| 34 | std::string datastr = datastrstream.str(); | 107 | std::string datastr = datastrstream.str(); |
| 35 | std::string url = "https://api.twitter.com/1.1/statuses/update.json"; | 108 | std::string url = "https://api.twitter.com/1.1/statuses/update.json"; |
| 36 | 109 | ||
| 110 | long response_code; | ||
| 111 | json response_data; | ||
| 112 | if (!performPost(url, datastr, response_code, response_data)) | ||
| 113 | { | ||
| 114 | return response::curl_error; | ||
| 115 | } | ||
| 116 | |||
| 117 | if (response_code == 200) | ||
| 118 | { | ||
| 119 | result = tweet(response_data); | ||
| 120 | return response::ok; | ||
| 121 | } else { | ||
| 122 | return codeForError(response_code, response_data); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | response client::uploadMedia(std::string media_type, const char* data, long data_length, long& media_id) | ||
| 127 | { | ||
| 128 | curl::curl_form form; | ||
| 129 | |||
| 130 | curl::curl_pair<CURLformoption, std::string> command_name(CURLFORM_COPYNAME, "command"); | ||
| 131 | curl::curl_pair<CURLformoption, std::string> command_cont(CURLFORM_COPYCONTENTS, "INIT"); | ||
| 132 | curl::curl_pair<CURLformoption, std::string> bytes_name(CURLFORM_COPYNAME, "total_bytes"); | ||
| 133 | curl::curl_pair<CURLformoption, std::string> bytes_cont(CURLFORM_COPYCONTENTS, std::to_string(data_length)); | ||
| 134 | curl::curl_pair<CURLformoption, std::string> type_name(CURLFORM_COPYNAME, "media_type"); | ||
| 135 | curl::curl_pair<CURLformoption, std::string> type_cont(CURLFORM_COPYCONTENTS, media_type); | ||
| 136 | form.add(command_name, command_cont); | ||
| 137 | form.add(bytes_name, bytes_cont); | ||
| 138 | form.add(type_name, type_cont); | ||
| 139 | |||
| 140 | if (media_type == "image/gif") | ||
| 141 | { | ||
| 142 | curl::curl_pair<CURLformoption, std::string> category_name(CURLFORM_COPYNAME, "media_category"); | ||
| 143 | curl::curl_pair<CURLformoption, std::string> category_cont(CURLFORM_COPYCONTENTS, "tweet_gif"); | ||
| 144 | form.add(category_name, category_cont); | ||
| 145 | } | ||
| 146 | |||
| 147 | long response_code; | ||
| 148 | json response_data; | ||
| 149 | if (!performMultiPost("https://upload.twitter.com/1.1/media/upload.json", form.get(), response_code, response_data)) | ||
| 150 | { | ||
| 151 | return response::curl_error; | ||
| 152 | } | ||
| 153 | |||
| 154 | if (response_code / 100 != 2) | ||
| 155 | { | ||
| 156 | return codeForError(response_code, response_data); | ||
| 157 | } | ||
| 158 | |||
| 159 | media_id = response_data["media_id"].get<long>(); | ||
| 160 | |||
| 161 | curl_httppost* append_form_post = nullptr; | ||
| 162 | curl_httppost* append_form_last = nullptr; | ||
| 163 | curl_formadd(&append_form_post, &append_form_last, CURLFORM_COPYNAME, "command", CURLFORM_COPYCONTENTS, "APPEND", CURLFORM_END); | ||
| 164 | curl_formadd(&append_form_post, &append_form_last, CURLFORM_COPYNAME, "media_id", CURLFORM_COPYCONTENTS, std::to_string(media_id).c_str(), CURLFORM_END); | ||
| 165 | curl_formadd(&append_form_post, &append_form_last, CURLFORM_COPYNAME, "media", CURLFORM_BUFFER, "media", CURLFORM_BUFFERPTR, data, CURLFORM_BUFFERLENGTH, data_length, CURLFORM_CONTENTTYPE, "application/octet-stream", CURLFORM_END); | ||
| 166 | curl_formadd(&append_form_post, &append_form_last, CURLFORM_COPYNAME, "segment_index", CURLFORM_COPYCONTENTS, std::to_string(0).c_str(), CURLFORM_END); | ||
| 167 | if (!performMultiPost("https://upload.twitter.com/1.1/media/upload.json", append_form_post, response_code, response_data)) | ||
| 168 | { | ||
| 169 | return response::curl_error; | ||
| 170 | } | ||
| 171 | |||
| 172 | curl_formfree(append_form_post); | ||
| 173 | |||
| 174 | if (response_code / 100 != 2) | ||
| 175 | { | ||
| 176 | return codeForError(response_code, response_data); | ||
| 177 | } | ||
| 178 | |||
| 179 | curl::curl_form finalize_form; | ||
| 180 | curl::curl_pair<CURLformoption, std::string> command3_name(CURLFORM_COPYNAME, "command"); | ||
| 181 | curl::curl_pair<CURLformoption, std::string> command3_cont(CURLFORM_COPYCONTENTS, "FINALIZE"); | ||
| 182 | curl::curl_pair<CURLformoption, std::string> media_id_name(CURLFORM_COPYNAME, "media_id"); | ||
| 183 | curl::curl_pair<CURLformoption, std::string> media_id_cont(CURLFORM_COPYCONTENTS, std::to_string(media_id)); | ||
| 184 | finalize_form.add(command3_name, command3_cont); | ||
| 185 | finalize_form.add(media_id_name, media_id_cont); | ||
| 186 | |||
| 187 | if (!performMultiPost("https://upload.twitter.com/1.1/media/upload.json", finalize_form.get(), response_code, response_data)) | ||
| 188 | { | ||
| 189 | return response::curl_error; | ||
| 190 | } | ||
| 191 | |||
| 192 | if (response_code / 100 != 2) | ||
| 193 | { | ||
| 194 | return codeForError(response_code, response_data); | ||
| 195 | } | ||
| 196 | |||
| 197 | if (response_data.find("processing_info") != response_data.end()) | ||
| 198 | { | ||
| 199 | std::stringstream datastr; | ||
| 200 | datastr << "https://upload.twitter.com/1.1/media/upload.json?command=STATUS&media_id=" << media_id; | ||
| 201 | |||
| 202 | for (;;) | ||
| 203 | { | ||
| 204 | if (!performGet(datastr.str(), response_code, response_data)) | ||
| 205 | { | ||
| 206 | return response::curl_error; | ||
| 207 | } | ||
| 208 | |||
| 209 | if (response_code / 100 != 2) | ||
| 210 | { | ||
| 211 | return codeForError(response_code, response_data); | ||
| 212 | } | ||
| 213 | |||
| 214 | if (response_data["processing_info"]["state"] == "succeeded") | ||
| 215 | { | ||
| 216 | break; | ||
| 217 | } | ||
| 218 | |||
| 219 | int ttw = response_data["processing_info"]["check_after_secs"].get<int>(); | ||
| 220 | sleep(ttw); | ||
| 221 | } | ||
| 222 | } | ||
| 223 | |||
| 224 | return response::ok; | ||
| 225 | } | ||
| 226 | |||
| 227 | bool client::performGet(std::string url, long& response_code, json& result) | ||
| 228 | { | ||
| 229 | std::ostringstream output; | ||
| 230 | curl::curl_ios<std::ostringstream> ios(output); | ||
| 231 | curl::curl_easy conn(ios); | ||
| 232 | |||
| 233 | curl::curl_header headers; | ||
| 234 | std::string oauth_header = _oauth_client->getFormattedHttpHeader(OAuth::Http::Get, url, ""); | ||
| 235 | if (!oauth_header.empty()) | ||
| 236 | { | ||
| 237 | headers.add(oauth_header); | ||
| 238 | } | ||
| 239 | |||
| 240 | try { | ||
| 241 | //conn.add<CURLOPT_VERBOSE>(1); | ||
| 242 | //conn.add<CURLOPT_DEBUGFUNCTION>(my_trace); | ||
| 243 | conn.add<CURLOPT_URL>(url.c_str()); | ||
| 244 | conn.add<CURLOPT_HTTPHEADER>(headers.get()); | ||
| 245 | |||
| 246 | conn.perform(); | ||
| 247 | } catch (curl::curl_easy_exception error) | ||
| 248 | { | ||
| 249 | error.print_traceback(); | ||
| 250 | |||
| 251 | return false; | ||
| 252 | } | ||
| 253 | |||
| 254 | response_code = conn.get_info<CURLINFO_RESPONSE_CODE>().get(); | ||
| 255 | if (output.str().empty()) | ||
| 256 | { | ||
| 257 | result = json(); | ||
| 258 | } else { | ||
| 259 | result = json::parse(output.str()); | ||
| 260 | } | ||
| 261 | |||
| 262 | return true; | ||
| 263 | } | ||
| 264 | |||
| 265 | bool client::performPost(std::string url, std::string datastr, long& response_code, json& result) | ||
| 266 | { | ||
| 267 | std::ostringstream output; | ||
| 268 | curl::curl_ios<std::ostringstream> ios(output); | ||
| 269 | curl::curl_easy conn(ios); | ||
| 270 | |||
| 37 | curl::curl_header headers; | 271 | curl::curl_header headers; |
| 38 | std::string oauth_header = _oauth_client->getFormattedHttpHeader(OAuth::Http::Post, url, datastr); | 272 | std::string oauth_header = _oauth_client->getFormattedHttpHeader(OAuth::Http::Post, url, datastr); |
| 39 | if (!oauth_header.empty()) | 273 | if (!oauth_header.empty()) |
| @@ -42,9 +276,10 @@ namespace twitter { | |||
| 42 | } | 276 | } |
| 43 | 277 | ||
| 44 | try { | 278 | try { |
| 279 | //conn.add<CURLOPT_VERBOSE>(1); | ||
| 280 | //conn.add<CURLOPT_DEBUGFUNCTION>(my_trace); | ||
| 45 | conn.add<CURLOPT_URL>(url.c_str()); | 281 | conn.add<CURLOPT_URL>(url.c_str()); |
| 46 | conn.add<CURLOPT_COPYPOSTFIELDS>(datastr.c_str()); | 282 | conn.add<CURLOPT_COPYPOSTFIELDS>(datastr.c_str()); |
| 47 | conn.add<CURLOPT_POST>(1); | ||
| 48 | conn.add<CURLOPT_HTTPHEADER>(headers.get()); | 283 | conn.add<CURLOPT_HTTPHEADER>(headers.get()); |
| 49 | 284 | ||
| 50 | conn.perform(); | 285 | conn.perform(); |
| @@ -52,17 +287,62 @@ namespace twitter { | |||
| 52 | { | 287 | { |
| 53 | error.print_traceback(); | 288 | error.print_traceback(); |
| 54 | 289 | ||
| 55 | return response::curl_error; | 290 | return false; |
| 56 | } | 291 | } |
| 57 | 292 | ||
| 58 | long response_code = conn.get_info<CURLINFO_RESPONSE_CODE>().get(); | 293 | response_code = conn.get_info<CURLINFO_RESPONSE_CODE>().get(); |
| 59 | json response_data = json::parse(output.str()); | 294 | if (output.str().empty()) |
| 60 | if (response_code == 200) | ||
| 61 | { | 295 | { |
| 62 | result = tweet(response_data); | 296 | result = json(); |
| 63 | return response::ok; | 297 | } else { |
| 298 | result = json::parse(output.str()); | ||
| 64 | } | 299 | } |
| 65 | 300 | ||
| 301 | return true; | ||
| 302 | } | ||
| 303 | |||
| 304 | bool client::performMultiPost(std::string url, const curl_httppost* fields, long& response_code, json& result) | ||
| 305 | { | ||
| 306 | std::ostringstream output; | ||
| 307 | curl::curl_ios<std::ostringstream> ios(output); | ||
| 308 | curl::curl_easy conn(ios); | ||
| 309 | |||
| 310 | curl::curl_header headers; | ||
| 311 | std::string oauth_header = _oauth_client->getFormattedHttpHeader(OAuth::Http::Post, url, ""); | ||
| 312 | if (!oauth_header.empty()) | ||
| 313 | { | ||
| 314 | headers.add(oauth_header); | ||
| 315 | } | ||
| 316 | |||
| 317 | try { | ||
| 318 | //conn.add<CURLOPT_VERBOSE>(1); | ||
| 319 | //conn.add<CURLOPT_DEBUGFUNCTION>(my_trace); | ||
| 320 | conn.add<CURLOPT_HTTPHEADER>(headers.get()); | ||
| 321 | conn.add<CURLOPT_URL>(url.c_str()); | ||
| 322 | conn.add<CURLOPT_HTTPPOST>(fields); | ||
| 323 | |||
| 324 | conn.perform(); | ||
| 325 | } catch (curl::curl_easy_exception error) | ||
| 326 | { | ||
| 327 | error.print_traceback(); | ||
| 328 | |||
| 329 | return false; | ||
| 330 | } | ||
| 331 | |||
| 332 | response_code = conn.get_info<CURLINFO_RESPONSE_CODE>().get(); | ||
| 333 | |||
| 334 | if (output.str().empty()) | ||
| 335 | { | ||
| 336 | result = json(); | ||
| 337 | } else { | ||
| 338 | result = json::parse(output.str()); | ||
| 339 | } | ||
| 340 | |||
| 341 | return true; | ||
| 342 | } | ||
| 343 | |||
| 344 | response client::codeForError(int response_code, json response_data) const | ||
| 345 | { | ||
| 66 | std::set<int> error_codes; | 346 | std::set<int> error_codes; |
| 67 | if (response_data.find("errors") != response_data.end()) | 347 | if (response_data.find("errors") != response_data.end()) |
| 68 | { | 348 | { |
| @@ -101,6 +381,9 @@ namespace twitter { | |||
| 101 | } else if (error_codes.count(261) == 1) | 381 | } else if (error_codes.count(261) == 1) |
| 102 | { | 382 | { |
| 103 | return response::write_restricted; | 383 | return response::write_restricted; |
| 384 | } else if (error_codes.count(44) == 1) | ||
| 385 | { | ||
| 386 | return response::invalid_media; | ||
| 104 | } else if (response_code == 429) | 387 | } else if (response_code == 429) |
| 105 | { | 388 | { |
| 106 | return response::limited; | 389 | return response::limited; |
| diff --git a/src/client.h b/src/client.h index 1ab5c70..3a133e4 100644 --- a/src/client.h +++ b/src/client.h | |||
| @@ -1,7 +1,12 @@ | |||
| 1 | #ifndef TWITTER_H_ABFF6A12 | 1 | #ifndef TWITTER_H_ABFF6A12 |
| 2 | #define TWITTER_H_ABFF6A12 | 2 | #define TWITTER_H_ABFF6A12 |
| 3 | 3 | ||
| 4 | #include "twitter.h" | 4 | #include "codes.h" |
| 5 | #include "tweet.h" | ||
| 6 | #include "auth.h" | ||
| 7 | #include <list> | ||
| 8 | #include <curl_easy.h> | ||
| 9 | #include <curl_header.h> | ||
| 5 | 10 | ||
| 6 | namespace OAuth { | 11 | namespace OAuth { |
| 7 | class Consumer; | 12 | class Consumer; |
| @@ -16,12 +21,18 @@ namespace twitter { | |||
| 16 | client(const auth& _auth); | 21 | client(const auth& _auth); |
| 17 | ~client(); | 22 | ~client(); |
| 18 | 23 | ||
| 19 | response updateStatus(std::string msg, tweet& result); | 24 | response updateStatus(std::string msg, tweet& result, std::list<long> media_ids = {}); |
| 25 | response uploadMedia(std::string media_type, const char* data, long data_length, long& media_id); | ||
| 20 | 26 | ||
| 21 | private: | 27 | private: |
| 22 | OAuth::Consumer* _oauth_consumer; | 28 | OAuth::Consumer* _oauth_consumer; |
| 23 | OAuth::Token* _oauth_token; | 29 | OAuth::Token* _oauth_token; |
| 24 | OAuth::Client* _oauth_client; | 30 | OAuth::Client* _oauth_client; |
| 31 | |||
| 32 | bool performGet(std::string url, long& response_code, json& result); | ||
| 33 | bool performPost(std::string url, std::string dataStr, long& response_code, json& result); | ||
| 34 | bool performMultiPost(std::string url, const curl_httppost* fields, long& response_code, json& result); | ||
| 35 | response codeForError(int httpcode, json errors) const; | ||
| 25 | }; | 36 | }; |
| 26 | 37 | ||
| 27 | }; | 38 | }; |
| diff --git a/src/codes.cpp b/src/codes.cpp new file mode 100644 index 0000000..9639d5d --- /dev/null +++ b/src/codes.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #include "codes.h" | ||
| 2 | |||
| 3 | std::ostream& operator<<(std::ostream& os, twitter::response r) | ||
| 4 | { | ||
| 5 | switch (r) | ||
| 6 | { | ||
| 7 | case twitter::response::ok: return os << "OK"; | ||
| 8 | case twitter::response::curl_error: return os << "Curl Error"; | ||
| 9 | case twitter::response::bad_auth: return os << "Bad Auth"; | ||
| 10 | case twitter::response::limited: return os << "Rate Limit Exceeded"; | ||
| 11 | case twitter::response::server_error: return os << "Twitter Server Error"; | ||
| 12 | case twitter::response::server_unavailable: return os << "Twitter Is Down"; | ||
| 13 | case twitter::response::server_overloaded: return os << "Twitter Is Over Capacity"; | ||
| 14 | case twitter::response::server_timeout: return os << "Twitter Connection Timed Out"; | ||
| 15 | case twitter::response::suspended: return os << "Authenticated User Is Suspended"; | ||
| 16 | case twitter::response::bad_token: return os << "Invalid Or Expired Access Token"; | ||
| 17 | case twitter::response::duplicate_status: return os << "Duplicate Status"; | ||
| 18 | case twitter::response::suspected_spam: return os << "Request Looks Automated"; | ||
| 19 | case twitter::response::write_restricted: return os << "Cannot Perform Write"; | ||
| 20 | case twitter::response::bad_length: return os << "Message Body Too Long"; | ||
| 21 | case twitter::response::unknown_error: return os << "Unknown Error"; | ||
| 22 | case twitter::response::invalid_media: return os << "Invalid Media"; | ||
| 23 | } | ||
| 24 | } | ||
| diff --git a/src/codes.h b/src/codes.h new file mode 100644 index 0000000..334f0ce --- /dev/null +++ b/src/codes.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | #ifndef CODES_H_05838D39 | ||
| 2 | #define CODES_H_05838D39 | ||
| 3 | |||
| 4 | #include <ostream> | ||
| 5 | |||
| 6 | namespace twitter { | ||
| 7 | |||
| 8 | enum class response { | ||
| 9 | ok, | ||
| 10 | curl_error, | ||
| 11 | bad_auth, | ||
| 12 | limited, | ||
| 13 | server_error, | ||
| 14 | server_unavailable, | ||
| 15 | server_overloaded, | ||
| 16 | server_timeout, | ||
| 17 | suspended, | ||
| 18 | bad_token, | ||
| 19 | duplicate_status, | ||
| 20 | suspected_spam, | ||
| 21 | write_restricted, | ||
| 22 | bad_length, | ||
| 23 | unknown_error, | ||
| 24 | invalid_media | ||
| 25 | }; | ||
| 26 | |||
| 27 | }; | ||
| 28 | |||
| 29 | std::ostream& operator<<(std::ostream& os, twitter::response r); | ||
| 30 | |||
| 31 | #endif /* end of include guard: CODES_H_05838D39 */ | ||
| diff --git a/src/tweet.cpp b/src/tweet.cpp index 165187e..3ba3aa3 100644 --- a/src/tweet.cpp +++ b/src/tweet.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | #include "twitter.h" | 1 | #include "tweet.h" |
| 2 | 2 | ||
| 3 | namespace twitter { | 3 | namespace twitter { |
| 4 | 4 | ||
| diff --git a/src/tweet.h b/src/tweet.h index 1d83aae..e099579 100644 --- a/src/tweet.h +++ b/src/tweet.h | |||
| @@ -1,6 +1,10 @@ | |||
| 1 | #ifndef TWEET_H_CE980721 | 1 | #ifndef TWEET_H_CE980721 |
| 2 | #define TWEET_H_CE980721 | 2 | #define TWEET_H_CE980721 |
| 3 | 3 | ||
| 4 | #include <json.hpp> | ||
| 5 | |||
| 6 | using nlohmann::json; | ||
| 7 | |||
| 4 | namespace twitter { | 8 | namespace twitter { |
| 5 | 9 | ||
| 6 | class tweet { | 10 | class tweet { |
| diff --git a/src/twitter.h b/src/twitter.h index 39618c9..f9534c6 100644 --- a/src/twitter.h +++ b/src/twitter.h | |||
| @@ -3,32 +3,12 @@ | |||
| 3 | 3 | ||
| 4 | namespace twitter { | 4 | namespace twitter { |
| 5 | 5 | ||
| 6 | enum class response { | ||
| 7 | ok, | ||
| 8 | curl_error, | ||
| 9 | bad_auth, | ||
| 10 | limited, | ||
| 11 | server_error, | ||
| 12 | server_unavailable, | ||
| 13 | server_overloaded, | ||
| 14 | server_timeout, | ||
| 15 | suspended, | ||
| 16 | bad_token, | ||
| 17 | duplicate_status, | ||
| 18 | suspected_spam, | ||
| 19 | write_restricted, | ||
| 20 | bad_length, | ||
| 21 | unknown_error | ||
| 22 | }; | ||
| 23 | |||
| 24 | class tweet; | 6 | class tweet; |
| 25 | 7 | ||
| 26 | }; | 8 | }; |
| 27 | 9 | ||
| 28 | #include <json.hpp> | 10 | #include "codes.h" |
| 29 | 11 | #include "util.h" | |
| 30 | using nlohmann::json; | ||
| 31 | |||
| 32 | #include "auth.h" | 12 | #include "auth.h" |
| 33 | #include "client.h" | 13 | #include "client.h" |
| 34 | #include "tweet.h" | 14 | #include "tweet.h" |
| diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..e1c9370 --- /dev/null +++ b/src/util.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | #ifndef UTIL_H_440DEAA0 | ||
| 2 | #define UTIL_H_440DEAA0 | ||
| 3 | |||
| 4 | #include <string> | ||
| 5 | #include <sstream> | ||
| 6 | |||
| 7 | namespace twitter { | ||
| 8 | |||
| 9 | template <class InputIterator> | ||
| 10 | std::string implode(InputIterator first, InputIterator last, std::string delimiter) | ||
| 11 | { | ||
| 12 | std::stringstream result; | ||
| 13 | |||
| 14 | for (InputIterator it = first; it != last; it++) | ||
| 15 | { | ||
| 16 | if (it != first) | ||
| 17 | { | ||
| 18 | result << delimiter; | ||
| 19 | } | ||
| 20 | |||
| 21 | result << *it; | ||
| 22 | } | ||
| 23 | |||
| 24 | return result.str(); | ||
| 25 | } | ||
| 26 | |||
| 27 | }; | ||
| 28 | |||
| 29 | #endif /* end of include guard: UTIL_H_440DEAA0 */ | ||
