From 891d57d200f55b91f80b6d3b4dd0c30479be6109 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Tue, 12 Apr 2016 18:40:52 -0400 Subject: Added basic ability to tweet --- .gitmodules | 9 ++++ CMakeLists.txt | 15 +++++++ src/auth.cpp | 45 +++++++++++++++++++ src/auth.h | 29 +++++++++++++ src/client.cpp | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/client.h | 29 +++++++++++++ src/tweet.cpp | 15 +++++++ src/tweet.h | 17 ++++++++ src/twitter.h | 36 ++++++++++++++++ vendor/curlcpp | 1 + vendor/json | 1 + vendor/liboauthcpp | 1 + 12 files changed, 322 insertions(+) create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 100644 src/auth.cpp create mode 100644 src/auth.h create mode 100644 src/client.cpp create mode 100644 src/client.h create mode 100644 src/tweet.cpp create mode 100644 src/tweet.h create mode 100644 src/twitter.h create mode 160000 vendor/curlcpp create mode 160000 vendor/json create mode 160000 vendor/liboauthcpp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..6d8effa --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "vendor/liboauthcpp"] + path = vendor/liboauthcpp + url = https://github.com/sirikata/liboauthcpp +[submodule "vendor/json"] + path = vendor/json + url = https://github.com/nlohmann/json +[submodule "vendor/curlcpp"] + path = vendor/curlcpp + url = https://github.com/JosephP91/curlcpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7507e25 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required (VERSION 3.1) +project (twitter++) + +include_directories(vendor/json/src) + +add_subdirectory(vendor/liboauthcpp/build EXCLUDE_FROM_ALL) +include_directories(vendor/liboauthcpp/include) + +add_subdirectory(vendor/curlcpp) +include_directories(${CURLCPP_SOURCE_DIR}/include) + +add_library(twitter++ src/client.cpp src/auth.cpp src/tweet.cpp) +set_property(TARGET twitter++ PROPERTY CXX_STANDARD 11) +set_property(TARGET twitter++ PROPERTY CXX_STANDARD_REQUIRED ON) +target_link_libraries(twitter++ oauthcpp curlcpp) diff --git a/src/auth.cpp b/src/auth.cpp new file mode 100644 index 0000000..325c521 --- /dev/null +++ b/src/auth.cpp @@ -0,0 +1,45 @@ +#include "twitter.h" + +namespace twitter { + + void auth::setConsumerKey(std::string _arg) + { + _consumer_key = _arg; + } + + void auth::setConsumerSecret(std::string _arg) + { + _consumer_secret = _arg; + } + + void auth::setAccessKey(std::string _arg) + { + _access_key = _arg; + } + + void auth::setAccessSecret(std::string _arg) + { + _access_secret = _arg; + } + + std::string auth::getConsumerKey() const + { + return _consumer_key; + } + + std::string auth::getConsumerSecret() const + { + return _consumer_secret; + } + + std::string auth::getAccessKey() const + { + return _access_key; + } + + std::string auth::getAccessSecret() const + { + return _access_secret; + } + +}; diff --git a/src/auth.h b/src/auth.h new file mode 100644 index 0000000..ef07e81 --- /dev/null +++ b/src/auth.h @@ -0,0 +1,29 @@ +#ifndef AUTH_H_48EF85FD +#define AUTH_H_48EF85FD + +#include + +namespace twitter { + + class auth { + public: + void setConsumerKey(std::string _arg); + void setConsumerSecret(std::string _arg); + void setAccessKey(std::string _arg); + void setAccessSecret(std::string _arg); + + std::string getConsumerKey() const; + std::string getConsumerSecret() const; + std::string getAccessKey() const; + std::string getAccessSecret() const; + + private: + std::string _consumer_key; + std::string _consumer_secret; + std::string _access_key; + std::string _access_secret; + }; + +}; + +#endif /* end of include guard: AUTH_H_48EF85FD */ diff --git a/src/client.cpp b/src/client.cpp new file mode 100644 index 0000000..b71ff70 --- /dev/null +++ b/src/client.cpp @@ -0,0 +1,124 @@ +#include "client.h" +#include +#include +#include +#include +#include +#include + +namespace twitter { + + client::client(const auth& _arg) + { + _oauth_consumer = new OAuth::Consumer(_arg.getConsumerKey(), _arg.getConsumerSecret()); + _oauth_token = new OAuth::Token(_arg.getAccessKey(), _arg.getAccessSecret()); + _oauth_client = new OAuth::Client(_oauth_consumer, _oauth_token); + } + + client::~client() + { + delete _oauth_client; + delete _oauth_token; + delete _oauth_consumer; + } + + response client::updateStatus(std::string msg, tweet& result) + { + std::ostringstream output; + curl::curl_ios ios(output); + curl::curl_easy conn(ios); + + std::stringstream datastrstream; + datastrstream << "status=" << OAuth::PercentEncode(msg); + + std::string datastr = datastrstream.str(); + std::string url = "https://api.twitter.com/1.1/statuses/update.json"; + + curl::curl_header headers; + std::string oauth_header = _oauth_client->getFormattedHttpHeader(OAuth::Http::Post, url, datastr); + if (!oauth_header.empty()) + { + headers.add(oauth_header); + } + + try { + conn.add(url.c_str()); + conn.add(datastr.c_str()); + conn.add(1); + conn.add(headers.get()); + + conn.perform(); + } catch (curl::curl_easy_exception error) + { + error.print_traceback(); + + return response::curl_error; + } + + long response_code = conn.get_info().get(); + json response_data = json::parse(output.str()); + if (response_code == 200) + { + result = tweet(response_data); + return response::ok; + } + + std::set error_codes; + if (response_data.find("errors") != response_data.end()) + { + std::transform(std::begin(response_data["errors"]), std::end(response_data["errors"]), std::inserter(error_codes, std::begin(error_codes)), [] (const json& error) { + return error["code"].get(); + }); + } + + if (error_codes.count(32) == 1 || error_codes.count(135) == 1 || error_codes.count(215) == 1) + { + return response::bad_auth; + } else if (error_codes.count(64) == 1) + { + return response::suspended; + } else if (error_codes.count(88) == 1 || error_codes.count(185) == 1) + { + return response::limited; + } else if (error_codes.count(89) == 1) + { + return response::bad_token; + } else if (error_codes.count(130) == 1) + { + return response::server_overloaded; + } else if (error_codes.count(131) == 1) + { + return response::server_error; + } else if (error_codes.count(186) == 1) + { + return response::bad_length; + } else if (error_codes.count(187) == 1) + { + return response::duplicate_status; + } else if (error_codes.count(226) == 1) + { + return response::suspected_spam; + } else if (error_codes.count(261) == 1) + { + return response::write_restricted; + } else if (response_code == 429) + { + return response::limited; + } else if (response_code == 500) + { + return response::server_error; + } else if (response_code == 502) + { + return response::server_unavailable; + } else if (response_code == 503) + { + return response::server_overloaded; + } else if (response_code == 504) + { + return response::server_timeout; + } else { + return response::unknown_error; + } + } + +}; diff --git a/src/client.h b/src/client.h new file mode 100644 index 0000000..1ab5c70 --- /dev/null +++ b/src/client.h @@ -0,0 +1,29 @@ +#ifndef TWITTER_H_ABFF6A12 +#define TWITTER_H_ABFF6A12 + +#include "twitter.h" + +namespace OAuth { + class Consumer; + class Token; + class Client; +}; + +namespace twitter { + + class client { + public: + client(const auth& _auth); + ~client(); + + response updateStatus(std::string msg, tweet& result); + + private: + OAuth::Consumer* _oauth_consumer; + OAuth::Token* _oauth_token; + OAuth::Client* _oauth_client; + }; + +}; + +#endif /* end of include guard: TWITTER_H_ABFF6A12 */ diff --git a/src/tweet.cpp b/src/tweet.cpp new file mode 100644 index 0000000..165187e --- /dev/null +++ b/src/tweet.cpp @@ -0,0 +1,15 @@ +#include "twitter.h" + +namespace twitter { + + tweet::tweet() + { + _valid = false; + } + + tweet::tweet(const json& data) + { + _valid = true; + } + +}; diff --git a/src/tweet.h b/src/tweet.h new file mode 100644 index 0000000..1d83aae --- /dev/null +++ b/src/tweet.h @@ -0,0 +1,17 @@ +#ifndef TWEET_H_CE980721 +#define TWEET_H_CE980721 + +namespace twitter { + + class tweet { + public: + tweet(); + tweet(const json& _data); + + private: + bool _valid; + }; + +}; + +#endif /* end of include guard: TWEET_H_CE980721 */ diff --git a/src/twitter.h b/src/twitter.h new file mode 100644 index 0000000..39618c9 --- /dev/null +++ b/src/twitter.h @@ -0,0 +1,36 @@ +#ifndef TWITTER_H_AC7A7666 +#define TWITTER_H_AC7A7666 + +namespace twitter { + + enum class response { + ok, + curl_error, + bad_auth, + limited, + server_error, + server_unavailable, + server_overloaded, + server_timeout, + suspended, + bad_token, + duplicate_status, + suspected_spam, + write_restricted, + bad_length, + unknown_error + }; + + class tweet; + +}; + +#include + +using nlohmann::json; + +#include "auth.h" +#include "client.h" +#include "tweet.h" + +#endif /* end of include guard: TWITTER_H_AC7A7666 */ diff --git a/vendor/curlcpp b/vendor/curlcpp new file mode 160000 index 0000000..0cdfb67 --- /dev/null +++ b/vendor/curlcpp @@ -0,0 +1 @@ +Subproject commit 0cdfb670d726252bdce4fb2a194e11de38a42e05 diff --git a/vendor/json b/vendor/json new file mode 160000 index 0000000..507322e --- /dev/null +++ b/vendor/json @@ -0,0 +1 @@ +Subproject commit 507322e6f2f63d028c68b2a666aefe902b77f66e diff --git a/vendor/liboauthcpp b/vendor/liboauthcpp new file mode 160000 index 0000000..4219b65 --- /dev/null +++ b/vendor/liboauthcpp @@ -0,0 +1 @@ +Subproject commit 4219b6576c53545d5f6b6f18a28ec93ec7969683 -- cgit 1.4.1