From 38e8795e068fbf89bb79c2795c61a6937138c651 Mon Sep 17 00:00:00 2001 From: keita Date: Fri, 19 Mar 2021 22:18:39 +0900 Subject: [PATCH 01/13] =?UTF-8?q?HTTP/GET=E3=81=AE=E5=AE=9F=E8=A3=85(#66)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cocoatweet/api/interface/httpGet.cc | 98 +++++++++++++++++++++++++ src/cocoatweet/api/interface/httpGet.h | 23 ++++++ 2 files changed, 121 insertions(+) create mode 100644 src/cocoatweet/api/interface/httpGet.cc create mode 100644 src/cocoatweet/api/interface/httpGet.h diff --git a/src/cocoatweet/api/interface/httpGet.cc b/src/cocoatweet/api/interface/httpGet.cc new file mode 100644 index 0000000..4dbdf0f --- /dev/null +++ b/src/cocoatweet/api/interface/httpGet.cc @@ -0,0 +1,98 @@ +#include +#include "cocoatweet/util/util.h" +#include +#include +#include +#include +#include +extern "C" { +#include +} + +#ifndef NDEBUG +#include +#endif + +namespace CocoaTweet::API::Interface { +void HttpGet::process(std::weak_ptr _oauth, + std::function _callback) { + auto url = url_; + + // エンドポイントへのパラメータにOAuthパラメータを付加して署名作成 + auto oauth = _oauth.lock(); + auto oauthParam = oauth->oauthParam(); + auto sigingParam = oauthParam; + if (contentType_ == "application/x-www-form-urlencoded") { + for (const auto [k, v] : bodyParam_) { + sigingParam.insert_or_assign(k, v); + } + } + + auto signature = oauth->signature(sigingParam, "GET", url_); + + // 作成した署名をエンドポイントへのパラメータ及びOAuthパラメータに登録 + oauthParam.merge(signature); + + // URLの構築 + { + std::vector tmp; + for (const auto& [key, value] : bodyParam_) { + tmp.push_back(key + "=" + value); + } + url_ += std::string("?" + CocoaTweet::Util::join(tmp, "&")); + } + + // ヘッダの構築 + std::string oauthHeader = "authorization: OAuth "; + { + std::vector tmp; + for (const auto& [key, value] : oauthParam) { + tmp.push_back(key + "=" + CocoaTweet::Util::urlEncode(value)); + } + oauthHeader += CocoaTweet::Util::join(tmp, ","); + } + + // do post + CURL* curl; + CURLcode res; + std::string rcv; + long responseCode; + curl = curl_easy_init(); + url_ = url_; + if (curl) { + curl_easy_setopt(curl, CURLOPT_URL, url_.c_str()); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlCallback_); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (std::string*)&rcv); +#ifndef NDEBUG + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); +#endif + // Headerを保持するcurl_slist*を初期化 + struct curl_slist* headers = NULL; + // Authorizationをヘッダに追加 + headers = curl_slist_append(headers, oauthHeader.c_str()); + + std::string contentType = ""; + if (contentType_ == "application/x-www-form-urlencoded") { + contentType = contentType_; + } else if (contentType_ == "multipart/form-data") { + contentType = contentType_ + "; boundary=milkcocoa0902"; + } + + headers = curl_slist_append(headers, ("Content-Type: " + contentType).c_str()); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode); + curl_easy_cleanup(curl); + } + + if (res != CURLE_OK) { + throw std::runtime_error(std::string("INTERNAL ERROR : curl(") + std::to_string(res) + ")"); + exit(1); + } + + if (_callback) { + _callback(responseCode, rcv); + } +} +} // namespace CocoaTweet::API::Interface diff --git a/src/cocoatweet/api/interface/httpGet.h b/src/cocoatweet/api/interface/httpGet.h new file mode 100644 index 0000000..86f2668 --- /dev/null +++ b/src/cocoatweet/api/interface/httpGet.h @@ -0,0 +1,23 @@ +#ifndef COCOATWEET_API_INTERFACE_HTTPGET_H_ +#define COCOATWEET_API_INTERFACE_HTTPGET_H_ + +#include +#include "cocoatweet/oauth/oauth.h" +#include + +namespace CocoaTweet::API::Interface { +/// @brief class for Send request with POST method +class HttpGet : public virtual HttpBase { +public: +protected: + /// @brief Send HTTP/POST using OAuth object + /// @param[in] std::weak_ptr _oauth : pointer to OAuth object to + /// authenticate + /// @param[in] std::function _callback : + /// callback method for processing to response + void process(std::weak_ptr _oauth, + std::function _callback); +}; +} // namespace CocoaTweet::API::Interface + +#endif From 4d2eecc47d007c48b5a946b02bcd6812407b30de Mon Sep 17 00:00:00 2001 From: keita Date: Fri, 19 Mar 2021 22:19:53 +0900 Subject: [PATCH 02/13] =?UTF-8?q?statuses=5Fusertimeline=E3=82=92=E5=8F=A9?= =?UTF-8?q?=E3=81=8F=E3=82=84=E3=81=A4=E3=81=AE=E5=AE=9F=E8=A3=85(#66)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cocoatweet/api/status/userTimeline.cc | 29 ++++++++++++++++++++++ src/cocoatweet/api/status/userTimeline.h | 30 +++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/cocoatweet/api/status/userTimeline.cc create mode 100644 src/cocoatweet/api/status/userTimeline.h diff --git a/src/cocoatweet/api/status/userTimeline.cc b/src/cocoatweet/api/status/userTimeline.cc new file mode 100644 index 0000000..7679ce9 --- /dev/null +++ b/src/cocoatweet/api/status/userTimeline.cc @@ -0,0 +1,29 @@ +#include "cocoatweet/api/status/userTimeline.h" +#include +#include "nlohmann/json.hpp" +#include + +namespace CocoaTweet::API::Statuses { +UserTimeline::UserTimeline() { + contentType_ = "application/x-www-form-urlencoded"; + url_ = "https://api.twitter.com/1.1/statuses/user_timeline.json"; +} + +void UserTimeline::screenName(const std::string& _screenName) { + bodyParam_.insert_or_assign("screen_name", _screenName); +} + +std::vector UserTimeline::process( + std::weak_ptr _oauth) { + std::vector tweet; + HttpGet::process(_oauth, [&tweet](const unsigned int _responseCode, const std::string& _rsv) { + auto json = nlohmann::json::parse(_rsv); + for (auto j : json) { + tweet.push_back(CocoaTweet::API::Model::Tweet::parse(_responseCode, j.dump())); + std::cout << j.dump() << std::endl; + } + }); + return tweet; +} + +} // namespace CocoaTweet::API::Statuses diff --git a/src/cocoatweet/api/status/userTimeline.h b/src/cocoatweet/api/status/userTimeline.h new file mode 100644 index 0000000..eca49fe --- /dev/null +++ b/src/cocoatweet/api/status/userTimeline.h @@ -0,0 +1,30 @@ +#ifndef COCOATWEET_API_STATUS_USERTIMELINE_H_ +#define COCOATWEET_API_STATUS_USERTIMELINE_H_ + +#include +#include +#include +#include +#include + +namespace CocoaTweet::API::Statuses { +/// @brief class for using statuses/update endpoint +class UserTimeline : public CocoaTweet::API::Interface::HttpGet { +public: + /// @brief primary constructor + UserTimeline(); + + void screenName(const std::string& _screenName); + + /// @brief process request for endpoint + /// @param[in] std::weak_ptr _oauth : pointer to oauth object + /// @param[out] CocoaTweet::API::Model::Tweet : request result + std::vector process( + std::weak_ptr _oauth); + +private: + std::string status_; +}; +} // namespace CocoaTweet::API::Statuses + +#endif From 73e0b9f90204f53524c448be9840b47c06242172 Mon Sep 17 00:00:00 2001 From: keita Date: Fri, 19 Mar 2021 22:28:06 +0900 Subject: [PATCH 03/13] =?UTF-8?q?status/user=5Ftimeline=E3=82=92=E5=8F=A9?= =?UTF-8?q?=E3=81=8F=E3=82=84=E3=81=A4=E3=81=AE=E8=BF=BD=E5=8A=A0(#66)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cocoatweet/api/status/status.cc | 9 ++++++++- src/cocoatweet/api/status/status.h | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cocoatweet/api/status/status.cc b/src/cocoatweet/api/status/status.cc index 02d3adf..babf1c8 100644 --- a/src/cocoatweet/api/status/status.cc +++ b/src/cocoatweet/api/status/status.cc @@ -2,6 +2,7 @@ #include "cocoatweet/api/status/update.h" #include "cocoatweet/api/status/destroy.h" #include "cocoatweet/api/status/retweet.h" +#include "cocoatweet/api/status/userTimeline.h" namespace CocoaTweet::API::Statuses { Status::Status(std::shared_ptr _oauth) { @@ -72,9 +73,15 @@ CocoaTweet::API::Model::Tweet Status::Destroy(const std::string& _id) const { return destroy.process(oauth_); } -CocoaTweet::API::Model::Tweet Status::Retweet(const std::string& _id) const{ +CocoaTweet::API::Model::Tweet Status::Retweet(const std::string& _id) const { CocoaTweet::API::Statuses::Retweet retweet; retweet.id(_id); return retweet.process(oauth_); } + +std::vector Status::UserTimeline(const std::string& _screenName) const{ + CocoaTweet::API::Statuses::UserTimeline userTimeline; + userTimeline.screenName(_screenName); + return userTimeline.process(oauth_); +} } // namespace CocoaTweet::API::Statuses diff --git a/src/cocoatweet/api/status/status.h b/src/cocoatweet/api/status/status.h index 3423cb4..b7d4113 100644 --- a/src/cocoatweet/api/status/status.h +++ b/src/cocoatweet/api/status/status.h @@ -62,6 +62,8 @@ public: CocoaTweet::API::Model::Tweet Retweet(const std::string& _id) const; + std::vector UserTimeline(const std::string& _screenName) const; + private: Options defaultOpt_; }; From 9413cd8ce2cd5d3e4aa4ffeb09563d063d30f573 Mon Sep 17 00:00:00 2001 From: keita Date: Fri, 19 Mar 2021 22:55:34 +0900 Subject: [PATCH 04/13] =?UTF-8?q?Model::Tweet=E3=81=8B=E3=82=89HttpPost?= =?UTF-8?q?=E3=81=AB=E3=82=A8=E3=83=A9=E3=83=BC=E3=83=8F=E3=83=B3=E3=83=89?= =?UTF-8?q?=E3=83=AA=E3=83=B3=E3=82=B0=E3=82=92=E7=A7=BB=E5=8B=95=E3=81=97?= =?UTF-8?q?=E3=81=9F(#67)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cocoatweet/api/favorite/create.cc | 7 +++-- src/cocoatweet/api/favorite/destroy.cc | 7 +++-- src/cocoatweet/api/interface/httpBase.h | 5 ++-- src/cocoatweet/api/interface/httpGet.cc | 4 +-- src/cocoatweet/api/interface/httpGet.h | 2 +- src/cocoatweet/api/interface/httpPost.cc | 31 ++++++++++++++++++++-- src/cocoatweet/api/interface/httpPost.h | 2 +- src/cocoatweet/api/media/upload.cc | 17 +++++------- src/cocoatweet/api/model/mediaStore.cc | 32 ++++++++++------------- src/cocoatweet/api/model/mediaStore.h | 9 ++----- src/cocoatweet/api/model/tweet.cc | 31 ++++------------------ src/cocoatweet/api/model/tweet.h | 9 ++----- src/cocoatweet/api/status/destroy.cc | 7 +++-- src/cocoatweet/api/status/retweet.cc | 18 ++++++------- src/cocoatweet/api/status/retweet.h | 14 +++++----- src/cocoatweet/api/status/status.cc | 7 ++--- src/cocoatweet/api/status/status.h | 2 +- src/cocoatweet/api/status/update.cc | 7 +++-- src/cocoatweet/api/status/userTimeline.cc | 6 ++--- test/api/model/tweet.cc | 12 ++++----- 20 files changed, 107 insertions(+), 122 deletions(-) diff --git a/src/cocoatweet/api/favorite/create.cc b/src/cocoatweet/api/favorite/create.cc index a181e1a..74a4358 100644 --- a/src/cocoatweet/api/favorite/create.cc +++ b/src/cocoatweet/api/favorite/create.cc @@ -13,10 +13,9 @@ void Create::id(const std::string& _id) { CocoaTweet::API::Model::Tweet Create::process(std::weak_ptr _oauth) { CocoaTweet::API::Model::Tweet tweet; - HttpPost::process(_oauth, - [&tweet](const unsigned int _responseCode, const std::string& _rcv) { - tweet = CocoaTweet::API::Model::Tweet(_responseCode, _rcv); - }); + HttpPost::process(_oauth, [&tweet](const std::string& _rcv) { + tweet = CocoaTweet::API::Model::Tweet(_rcv); + }); return tweet; } diff --git a/src/cocoatweet/api/favorite/destroy.cc b/src/cocoatweet/api/favorite/destroy.cc index 126eac6..ef88c9a 100644 --- a/src/cocoatweet/api/favorite/destroy.cc +++ b/src/cocoatweet/api/favorite/destroy.cc @@ -14,10 +14,9 @@ void Destroy::id(const std::string& _id) { CocoaTweet::API::Model::Tweet Destroy::process( std::weak_ptr _oauth) { CocoaTweet::API::Model::Tweet tweet; - HttpPost::process(_oauth, - [&tweet](const unsigned int _responseCode, const std::string& _rcv) { - tweet = CocoaTweet::API::Model::Tweet(_responseCode, _rcv); - }); + HttpPost::process(_oauth, [&tweet](const std::string& _rcv) { + tweet = CocoaTweet::API::Model::Tweet(_rcv); + }); return tweet; } diff --git a/src/cocoatweet/api/interface/httpBase.h b/src/cocoatweet/api/interface/httpBase.h index b5dffc7..e6314a3 100644 --- a/src/cocoatweet/api/interface/httpBase.h +++ b/src/cocoatweet/api/interface/httpBase.h @@ -12,9 +12,8 @@ protected: std::map bodyParam_; std::string url_; std::string contentType_; - virtual void process( - std::weak_ptr _oauth, - std::function _callback) = 0; + virtual void process(std::weak_ptr _oauth, + std::function _callback) = 0; static size_t curlCallback_(char* _ptr, size_t _size, size_t _nmemb, std::string* _stream) { int realsize = _size * _nmemb; _stream->append(_ptr, realsize); diff --git a/src/cocoatweet/api/interface/httpGet.cc b/src/cocoatweet/api/interface/httpGet.cc index 4dbdf0f..f1f26db 100644 --- a/src/cocoatweet/api/interface/httpGet.cc +++ b/src/cocoatweet/api/interface/httpGet.cc @@ -15,7 +15,7 @@ extern "C" { namespace CocoaTweet::API::Interface { void HttpGet::process(std::weak_ptr _oauth, - std::function _callback) { + std::function _callback) { auto url = url_; // エンドポイントへのパラメータにOAuthパラメータを付加して署名作成 @@ -92,7 +92,7 @@ void HttpGet::process(std::weak_ptr _oauth, } if (_callback) { - _callback(responseCode, rcv); + _callback(rcv); } } } // namespace CocoaTweet::API::Interface diff --git a/src/cocoatweet/api/interface/httpGet.h b/src/cocoatweet/api/interface/httpGet.h index 86f2668..bf98421 100644 --- a/src/cocoatweet/api/interface/httpGet.h +++ b/src/cocoatweet/api/interface/httpGet.h @@ -16,7 +16,7 @@ protected: /// @param[in] std::function _callback : /// callback method for processing to response void process(std::weak_ptr _oauth, - std::function _callback); + std::function _callback); }; } // namespace CocoaTweet::API::Interface diff --git a/src/cocoatweet/api/interface/httpPost.cc b/src/cocoatweet/api/interface/httpPost.cc index ebed8cb..378c280 100644 --- a/src/cocoatweet/api/interface/httpPost.cc +++ b/src/cocoatweet/api/interface/httpPost.cc @@ -1,5 +1,11 @@ #include #include "cocoatweet/util/util.h" +#include +#include +#include +#include +#include +#include "nlohmann/json.hpp" #include #include #include @@ -15,7 +21,7 @@ extern "C" { namespace CocoaTweet::API::Interface { void HttpPost::process(std::weak_ptr _oauth, - std::function _callback) { + std::function _callback) { // エンドポイントへのパラメータにOAuthパラメータを付加して署名作成 auto oauth = _oauth.lock(); auto oauthParam = oauth->oauthParam(); @@ -103,8 +109,29 @@ void HttpPost::process(std::weak_ptr _oauth, exit(1); } + if ((responseCode / 100) == 4) { + auto j = nlohmann::json::parse(rcv); + auto error = j["errors"][0]["code"]; + auto message = j["errors"][0]["message"]; + if (j.count("error") != 0) { + // この形式はエラーコードを持たないのでエラー種別が特定できない + throw new CocoaTweet::Exception::Exception(j["error"]); + } + if (error.get() == 144) { + throw CocoaTweet::Exception::TweetNotFoundException(message.get().c_str()); + } else if (error.get() == 32) { + throw CocoaTweet::Exception::AuthenticateException(message.get().c_str()); + } else if (error.get() == 187) { + throw CocoaTweet::Exception::TweetDuplicateException(message.get().c_str()); + } else if (error.get() == 88 || error.get() == 185) { + throw CocoaTweet::Exception::RateLimitException(message.get().c_str()); + } else if (error.get() == 186) { + throw CocoaTweet::Exception::TweetTooLongException(message.get().c_str()); + } + } + if (_callback) { - _callback(responseCode, rcv); + _callback(rcv); } } } // namespace CocoaTweet::API::Interface diff --git a/src/cocoatweet/api/interface/httpPost.h b/src/cocoatweet/api/interface/httpPost.h index 2547796..441fe58 100644 --- a/src/cocoatweet/api/interface/httpPost.h +++ b/src/cocoatweet/api/interface/httpPost.h @@ -16,7 +16,7 @@ protected: /// @param[in] std::function _callback : /// callback method for processing to response void process(std::weak_ptr _oauth, - std::function _callback); + std::function _callback); }; } // namespace CocoaTweet::API::Interface diff --git a/src/cocoatweet/api/media/upload.cc b/src/cocoatweet/api/media/upload.cc index bd10fc0..43de855 100644 --- a/src/cocoatweet/api/media/upload.cc +++ b/src/cocoatweet/api/media/upload.cc @@ -43,10 +43,9 @@ CocoaTweet::API::Model::MediaStore Upload::process( bodyParam_.insert_or_assign( "media_type", mimeType.at(std::filesystem::path(media_).extension().string())); - HttpPost::process(_oauth, - [&media](const unsigned int _responseCode, const std::string& _rsv) { - media = CocoaTweet::API::Model::MediaStore::parse(_responseCode, _rsv); - }); + HttpPost::process(_oauth, [&media](const std::string& _rcv) { + media = CocoaTweet::API::Model::MediaStore::parse(_rcv); + }); bodyParam_.insert_or_assign("media_id", media.id()); } @@ -63,7 +62,7 @@ CocoaTweet::API::Model::MediaStore Upload::process( bodyParam_.insert_or_assign("command", "APPEND"); bodyParam_.insert_or_assign("segment_index", std::to_string(segment)); bodyParam_.insert_or_assign("media", data.substr(segment * chunk, chunk)); - HttpPost::process(_oauth, [](const unsigned int _responseCode, const std::string& _rsv) { + HttpPost::process(_oauth, [](const std::string& _rsv) { // std::cout << _responseCode << std::endl << _rsv<< std::endl; }); segment++; @@ -76,11 +75,9 @@ CocoaTweet::API::Model::MediaStore Upload::process( bodyParam_.insert_or_assign("command", "FINALIZE"); bodyParam_.erase("segment_index"); bodyParam_.erase("media"); - HttpPost::process(_oauth, - [&media](const unsigned int _responseCode, const std::string& _rsv) { - std::cout << _responseCode << std::endl << _rsv << std::endl; - media = CocoaTweet::API::Model::MediaStore::parse(_responseCode, _rsv); - }); + HttpPost::process(_oauth, [&media](const std::string& _rcv) { + media = CocoaTweet::API::Model::MediaStore::parse(_rcv); + }); } // STATUS if needed diff --git a/src/cocoatweet/api/model/mediaStore.cc b/src/cocoatweet/api/model/mediaStore.cc index 10f2cd0..a293b3a 100644 --- a/src/cocoatweet/api/model/mediaStore.cc +++ b/src/cocoatweet/api/model/mediaStore.cc @@ -3,31 +3,27 @@ #include "nlohmann/json.hpp" namespace CocoaTweet::API::Model { -MediaStore MediaStore::parse(const unsigned int _responseCode, const std::string& _json) { +MediaStore MediaStore::parse(const std::string& _json) { auto j = nlohmann::json::parse(_json); MediaStore media; - if (_responseCode / 100 == 2) { - if (j.count("media_id_string") != 0) { - media.id(j["media_id_string"]); - } + if (j.count("media_id_string") != 0) { + media.id(j["media_id_string"]); + } - if (j.count("size") != 0) { - media.size(j["size"]); - } + if (j.count("size") != 0) { + media.size(j["size"]); + } - if (j.count("expires_after_secs") != 0) { - media.expires(j["expires_after_secs"]); - } + if (j.count("expires_after_secs") != 0) { + media.expires(j["expires_after_secs"]); + } - if (j.count("processing_info") == 0) { - media.state("succeeded"); - } else { - media.state(j["processing_info"]["state"]); - media.remain(j["processing_info"]["check_after_secs"].get()); - } + if (j.count("processing_info") == 0) { + media.state("succeeded"); } else { - throw new CocoaTweet::Exception::Exception(j["error"]); + media.state(j["processing_info"]["state"]); + media.remain(j["processing_info"]["check_after_secs"].get()); } return media; diff --git a/src/cocoatweet/api/model/mediaStore.h b/src/cocoatweet/api/model/mediaStore.h index 145282b..047dbfd 100644 --- a/src/cocoatweet/api/model/mediaStore.h +++ b/src/cocoatweet/api/model/mediaStore.h @@ -15,18 +15,13 @@ public: MediaStore(const MediaStore&) = default; /// @brief constructor for create object from json response - /// @param[in] const unsigned int _responseCode : http status code which received when post - /// request /// @param[in] const std::string& _json : received content from twitter endpoint - MediaStore(const unsigned int _responseCode, const std::string& _json) - : MediaStore(MediaStore::parse(_responseCode, _json)) {} + MediaStore(const std::string& _json) : MediaStore(MediaStore::parse(_json)) {} /// @brief response parser for MediaStore object - /// @param[in] const unsigned int _responseCode : http status code which received when post - /// request /// @param[in] const std::string& _json : received content from twitter endpoint /// @param[out] CocoaTweet::API::Model::MediaStore - static MediaStore parse(const unsigned int _responseCode, const std::string& _json); + static MediaStore parse(const std::string& _json); /// @brief set id of tweet /// @param[in] const std::string _id : media id to set diff --git a/src/cocoatweet/api/model/tweet.cc b/src/cocoatweet/api/model/tweet.cc index 3bf3fb7..27064d0 100644 --- a/src/cocoatweet/api/model/tweet.cc +++ b/src/cocoatweet/api/model/tweet.cc @@ -1,36 +1,15 @@ #include -#include -#include -#include -#include -#include #include "nlohmann/json.hpp" namespace CocoaTweet::API::Model { -Tweet Tweet::parse(const unsigned int _responseCode, const std::string& _json) { +Tweet Tweet::parse(const std::string& _json) { auto j = nlohmann::json::parse(_json); Tweet tweet; - if (_responseCode == 200) { - tweet.id(j["id_str"]); - tweet.createdAt(j["created_at"]); - tweet.text(j["text"]); - tweet.source(j["source"]); - } else { - auto error = j["errors"][0]["code"]; - auto message = j["errors"][0]["message"]; - if (error.get() == 144) { - throw CocoaTweet::Exception::TweetNotFoundException(message.get().c_str()); - } else if (error.get() == 32) { - throw CocoaTweet::Exception::AuthenticateException(message.get().c_str()); - } else if (error.get() == 187) { - throw CocoaTweet::Exception::TweetDuplicateException(message.get().c_str()); - } else if (error.get() == 88 || error.get() == 185) { - throw CocoaTweet::Exception::RateLimitException(message.get().c_str()); - } else if (error.get() == 186) { - throw CocoaTweet::Exception::TweetTooLongException(message.get().c_str()); - } - } + tweet.id(j["id_str"]); + tweet.createdAt(j["created_at"]); + tweet.text(j["text"]); + tweet.source(j["source"]); return tweet; } diff --git a/src/cocoatweet/api/model/tweet.h b/src/cocoatweet/api/model/tweet.h index 5ad6b6c..8e16a5c 100644 --- a/src/cocoatweet/api/model/tweet.h +++ b/src/cocoatweet/api/model/tweet.h @@ -15,18 +15,13 @@ public: Tweet(const Tweet&) = default; /// @brief constructor for create object from json response - /// @param[in] const unsigned int _responseCode : http status code which received when post - /// request /// @param[in] const std::string& _json : received content from twitter endpoint - Tweet(const unsigned int _responseCode, const std::string& _json) - : Tweet(Tweet::parse(_responseCode, _json)) {} + Tweet(const std::string& _json) : Tweet(Tweet::parse(_json)) {} /// @brief response parser for tweet object - /// @param[in] const unsigned int _responseCode : http status code which received when post - /// request /// @param[in] const std::string& _json : received content from twitter endpoint /// @param[out] CocoaTweet::API::Model::Tweet - static Tweet parse(const unsigned int _responseCode, const std::string& _json); + static Tweet parse(const std::string& _json); /// @brief set id of tweet /// @param[in] const std::string _id : tweet id to set diff --git a/src/cocoatweet/api/status/destroy.cc b/src/cocoatweet/api/status/destroy.cc index bee285e..caa0860 100644 --- a/src/cocoatweet/api/status/destroy.cc +++ b/src/cocoatweet/api/status/destroy.cc @@ -11,10 +11,9 @@ void Destroy::id(const std::string _id) { CocoaTweet::API::Model::Tweet Destroy::process( std::weak_ptr _oauth) { CocoaTweet::API::Model::Tweet tweet; - HttpPost::process(_oauth, - [&tweet](const unsigned int _responseCode, const std::string& _rsv) { - tweet = CocoaTweet::API::Model::Tweet::parse(_responseCode, _rsv); - }); + HttpPost::process(_oauth, [&tweet](const std::string& _rcv) { + tweet = CocoaTweet::API::Model::Tweet::parse(_rcv); + }); return tweet; } diff --git a/src/cocoatweet/api/status/retweet.cc b/src/cocoatweet/api/status/retweet.cc index 0f7877d..10203ce 100644 --- a/src/cocoatweet/api/status/retweet.cc +++ b/src/cocoatweet/api/status/retweet.cc @@ -2,20 +2,20 @@ #include namespace CocoaTweet::API::Statuses { - Retweet::Retweet(){} +Retweet::Retweet() {} - void Retweet::id(const std::string& _id){ +void Retweet::id(const std::string& _id) { contentType_ = "application/x-www-form-urlencoded"; url_ = "https://api.twitter.com/1.1/statuses/retweet/" + _id + ".json"; - } +} - CocoaTweet::API::Model::Tweet Retweet::process(std::weak_ptr _oauth){ +CocoaTweet::API::Model::Tweet Retweet::process( + std::weak_ptr _oauth) { CocoaTweet::API::Model::Tweet tweet; - HttpPost::process(_oauth, - [&tweet](const unsigned int _responseCode, const std::string& _rcv) { - tweet = CocoaTweet::API::Model::Tweet(_responseCode, _rcv); - }); + HttpPost::process(_oauth, [&tweet](const std::string& _rcv) { + tweet = CocoaTweet::API::Model::Tweet(_rcv); + }); return tweet; - } } +} // namespace CocoaTweet::API::Statuses diff --git a/src/cocoatweet/api/status/retweet.h b/src/cocoatweet/api/status/retweet.h index 500f5e4..add7a97 100644 --- a/src/cocoatweet/api/status/retweet.h +++ b/src/cocoatweet/api/status/retweet.h @@ -5,14 +5,14 @@ #include namespace CocoaTweet::API::Statuses { - class Retweet : public CocoaTweet::API::Interface::HttpPost{ - public: - Retweet(); +class Retweet : public CocoaTweet::API::Interface::HttpPost { +public: + Retweet(); - void id(const std::string& _id); + void id(const std::string& _id); - CocoaTweet::API::Model::Tweet process(std::weak_ptr _oauth); - }; -} + CocoaTweet::API::Model::Tweet process(std::weak_ptr _oauth); +}; +} // namespace CocoaTweet::API::Statuses #endif \ No newline at end of file diff --git a/src/cocoatweet/api/status/status.cc b/src/cocoatweet/api/status/status.cc index babf1c8..bf3a4c9 100644 --- a/src/cocoatweet/api/status/status.cc +++ b/src/cocoatweet/api/status/status.cc @@ -79,9 +79,10 @@ CocoaTweet::API::Model::Tweet Status::Retweet(const std::string& _id) const { return retweet.process(oauth_); } -std::vector Status::UserTimeline(const std::string& _screenName) const{ +std::vector Status::UserTimeline( + const std::string& _screenName) const { CocoaTweet::API::Statuses::UserTimeline userTimeline; - userTimeline.screenName(_screenName); - return userTimeline.process(oauth_); + userTimeline.screenName(_screenName); + return userTimeline.process(oauth_); } } // namespace CocoaTweet::API::Statuses diff --git a/src/cocoatweet/api/status/status.h b/src/cocoatweet/api/status/status.h index b7d4113..780772e 100644 --- a/src/cocoatweet/api/status/status.h +++ b/src/cocoatweet/api/status/status.h @@ -62,7 +62,7 @@ public: CocoaTweet::API::Model::Tweet Retweet(const std::string& _id) const; - std::vector UserTimeline(const std::string& _screenName) const; + std::vector UserTimeline(const std::string& _screenName) const; private: Options defaultOpt_; diff --git a/src/cocoatweet/api/status/update.cc b/src/cocoatweet/api/status/update.cc index 3395d65..866ad8b 100644 --- a/src/cocoatweet/api/status/update.cc +++ b/src/cocoatweet/api/status/update.cc @@ -55,10 +55,9 @@ void Update::failDMCommands(bool _fail) { CocoaTweet::API::Model::Tweet Update::process(std::weak_ptr _oauth) { CocoaTweet::API::Model::Tweet tweet; - HttpPost::process(_oauth, - [&tweet](const unsigned int _responseCode, const std::string& _rsv) { - tweet = CocoaTweet::API::Model::Tweet::parse(_responseCode, _rsv); - }); + HttpPost::process(_oauth, [&tweet](const std::string& _rcv) { + tweet = CocoaTweet::API::Model::Tweet::parse(_rcv); + }); return tweet; } diff --git a/src/cocoatweet/api/status/userTimeline.cc b/src/cocoatweet/api/status/userTimeline.cc index 7679ce9..52f3405 100644 --- a/src/cocoatweet/api/status/userTimeline.cc +++ b/src/cocoatweet/api/status/userTimeline.cc @@ -16,10 +16,10 @@ void UserTimeline::screenName(const std::string& _screenName) { std::vector UserTimeline::process( std::weak_ptr _oauth) { std::vector tweet; - HttpGet::process(_oauth, [&tweet](const unsigned int _responseCode, const std::string& _rsv) { - auto json = nlohmann::json::parse(_rsv); + HttpGet::process(_oauth, [&tweet](const std::string& _rcv) { + auto json = nlohmann::json::parse(_rcv); for (auto j : json) { - tweet.push_back(CocoaTweet::API::Model::Tweet::parse(_responseCode, j.dump())); + tweet.push_back(CocoaTweet::API::Model::Tweet::parse(j.dump())); std::cout << j.dump() << std::endl; } }); diff --git a/test/api/model/tweet.cc b/test/api/model/tweet.cc index c7450c7..4420f5b 100644 --- a/test/api/model/tweet.cc +++ b/test/api/model/tweet.cc @@ -27,7 +27,7 @@ BOOST_AUTO_TEST_CASE(test02) { "source" : "Twitter for Android" })"; - CocoaTweet::API::Model::Tweet tweet(200, json); + CocoaTweet::API::Model::Tweet tweet(json); BOOST_TEST(tweet.id() == "1234567890"); BOOST_TEST(tweet.createdAt() == "Thu Mar 04 00:00:00 +0000 2021"); BOOST_TEST(tweet.text() == "tweet"); @@ -42,7 +42,7 @@ BOOST_AUTO_TEST_CASE(test03) { }] })"; - BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(401, json), + BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(json), CocoaTweet::Exception::AuthenticateException); } @@ -54,7 +54,7 @@ BOOST_AUTO_TEST_CASE(test04) { }] })"; - BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(429, json), + BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(json), CocoaTweet::Exception::RateLimitException); } @@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(test05) { }] })"; - BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(403, json), + BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(json), CocoaTweet::Exception::RateLimitException); } @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(test06) { }] })"; - BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(403, json), + BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(json), CocoaTweet::Exception::TweetTooLongException); } @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(test07) { }] })"; - BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(403, json), + BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(json), CocoaTweet::Exception::TweetDuplicateException); } BOOST_AUTO_TEST_SUITE_END() From f8b74807375a301de4549dec6eafac2eef5ed218 Mon Sep 17 00:00:00 2001 From: keita Date: Fri, 19 Mar 2021 23:03:40 +0900 Subject: [PATCH 05/13] =?UTF-8?q?=E5=AD=98=E5=9C=A8=E3=81=97=E3=81=AA?= =?UTF-8?q?=E3=81=8F=E3=81=AA=E3=81=A3=E3=81=9F=E3=83=91=E3=82=B9=E3=82=92?= =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=81=8B=E3=82=89=E6=B6=88=E3=81=97?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/api/model/tweet.cc | 59 ----------------------------------------- 1 file changed, 59 deletions(-) diff --git a/test/api/model/tweet.cc b/test/api/model/tweet.cc index 4420f5b..de520d0 100644 --- a/test/api/model/tweet.cc +++ b/test/api/model/tweet.cc @@ -34,63 +34,4 @@ BOOST_AUTO_TEST_CASE(test02) { BOOST_TEST(tweet.source() == "Twitter for Android"); } -BOOST_AUTO_TEST_CASE(test03) { - std::string json = R"({ - "errors" : [{ - "code" : 32, - "message" : "Could not authenticate you." - }] - })"; - - BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(json), - CocoaTweet::Exception::AuthenticateException); -} - -BOOST_AUTO_TEST_CASE(test04) { - std::string json = R"({ - "errors" : [{ - "code" : 88, - "message" : "Rate limit exceeded." - }] - })"; - - BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(json), - CocoaTweet::Exception::RateLimitException); -} - -BOOST_AUTO_TEST_CASE(test05) { - std::string json = R"({ - "errors" : [{ - "code" : 185, - "message" : "User is over daily status update limit." - }] - })"; - - BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(json), - CocoaTweet::Exception::RateLimitException); -} - -BOOST_AUTO_TEST_CASE(test06) { - std::string json = R"({ - "errors" : [{ - "code" : 186, - "message" : "Tweet needs to be a bit shorter." - }] - })"; - - BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(json), - CocoaTweet::Exception::TweetTooLongException); -} - -BOOST_AUTO_TEST_CASE(test07) { - std::string json = R"({ - "errors" : [{ - "code" : 187, - "message" : "Status is a duplicate." - }] - })"; - - BOOST_CHECK_THROW(CocoaTweet::API::Model::Tweet(json), - CocoaTweet::Exception::TweetDuplicateException); -} BOOST_AUTO_TEST_SUITE_END() From e32356eca39af255ae9e4f6cdafaec8d8105fc45 Mon Sep 17 00:00:00 2001 From: keita Date: Fri, 19 Mar 2021 23:05:08 +0900 Subject: [PATCH 06/13] =?UTF-8?q?Status::UserTimeline=E3=81=A7std::cout?= =?UTF-8?q?=E3=81=B8=E3=81=AE=E3=83=80=E3=83=B3=E3=83=97=E3=82=92=E6=B6=88?= =?UTF-8?q?=E3=81=97=E3=81=9F(#66)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cocoatweet/api/status/userTimeline.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cocoatweet/api/status/userTimeline.cc b/src/cocoatweet/api/status/userTimeline.cc index 52f3405..7da4a3f 100644 --- a/src/cocoatweet/api/status/userTimeline.cc +++ b/src/cocoatweet/api/status/userTimeline.cc @@ -1,7 +1,6 @@ #include "cocoatweet/api/status/userTimeline.h" #include #include "nlohmann/json.hpp" -#include namespace CocoaTweet::API::Statuses { UserTimeline::UserTimeline() { @@ -20,7 +19,6 @@ std::vector UserTimeline::process( auto json = nlohmann::json::parse(_rcv); for (auto j : json) { tweet.push_back(CocoaTweet::API::Model::Tweet::parse(j.dump())); - std::cout << j.dump() << std::endl; } }); return tweet; From 561f255a767367bf9350aa3e18e3d8ed4d2353f3 Mon Sep 17 00:00:00 2001 From: keita Date: Fri, 19 Mar 2021 23:08:02 +0900 Subject: [PATCH 07/13] manage README --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 01ea18b..0f538db 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ you can use these endpoint - statuses/update - statuses/destroy/:id - statuses/retweet/:id +- statuses/user_timeline - favorites/create - favorites/destroy - media/upload(support: jpg, jpeg, png, gif, mp4) @@ -132,6 +133,13 @@ api.favorite().Create("tweet id"); // un Fav. a tweet api.favorite().Destroy("tweet id"); + +// get a timeline with screen name +auto timeline = api.status().UserTimeline("milkcocoa0902"); + ``` -donate by BitCoin : bc1qhpm8tmq72scqpl2ccemcf0ktfjg4rsu73e99tz \ No newline at end of file +# More Information +See [API Document](https://cocoatweet.milkcocoa.info) + +donate by BitCoin : bc1qhpm8tmq72scqpl2ccemcf0ktfjg4rsu73e99tz From 576a4a5ea37ba49556972cfd380eee92bf43a511 Mon Sep 17 00:00:00 2001 From: keita Date: Fri, 19 Mar 2021 23:13:13 +0900 Subject: [PATCH 08/13] manage comment --- src/cocoatweet/api/status/userTimeline.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cocoatweet/api/status/userTimeline.h b/src/cocoatweet/api/status/userTimeline.h index eca49fe..d01d985 100644 --- a/src/cocoatweet/api/status/userTimeline.h +++ b/src/cocoatweet/api/status/userTimeline.h @@ -8,17 +8,19 @@ #include namespace CocoaTweet::API::Statuses { -/// @brief class for using statuses/update endpoint +/// @brief class for using statuses/user_timeline endpoint class UserTimeline : public CocoaTweet::API::Interface::HttpGet { public: /// @brief primary constructor UserTimeline(); + /// @brief set screen name to get timeline + /// @param[in] const std::string& _screenName : screen name for getting tweet void screenName(const std::string& _screenName); /// @brief process request for endpoint /// @param[in] std::weak_ptr _oauth : pointer to oauth object - /// @param[out] CocoaTweet::API::Model::Tweet : request result + /// @param[out] std::vector : request result std::vector process( std::weak_ptr _oauth); From 81d248151ab09901fc356ba4aa3a068c6282783a Mon Sep 17 00:00:00 2001 From: keita Date: Sat, 20 Mar 2021 10:26:31 +0900 Subject: [PATCH 09/13] =?UTF-8?q?statuses/unretweet/:id=E3=82=92=E5=8F=A9?= =?UTF-8?q?=E3=81=8F=E3=82=84=E3=81=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cocoatweet/api/status/unretweet.cc | 21 +++++++++++++++++++++ src/cocoatweet/api/status/unretweet.h | 18 ++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/cocoatweet/api/status/unretweet.cc create mode 100644 src/cocoatweet/api/status/unretweet.h diff --git a/src/cocoatweet/api/status/unretweet.cc b/src/cocoatweet/api/status/unretweet.cc new file mode 100644 index 0000000..92378da --- /dev/null +++ b/src/cocoatweet/api/status/unretweet.cc @@ -0,0 +1,21 @@ +#include +#include + +namespace CocoaTweet::API::Statuses { +Unretweet::Unretweet() {} + +void Unretweet::id(const std::string& _id) { + contentType_ = "application/x-www-form-urlencoded"; + url_ = "https://api.twitter.com/1.1/statuses/unretweet/" + _id + ".json"; +} + +CocoaTweet::API::Model::Tweet Unretweet::process( + std::weak_ptr _oauth) { + CocoaTweet::API::Model::Tweet tweet; + HttpPost::process(_oauth, [&tweet](const std::string& _rcv) { + tweet = CocoaTweet::API::Model::Tweet(_rcv); + }); + + return tweet; +} +} // namespace CocoaTweet::API::Statuses diff --git a/src/cocoatweet/api/status/unretweet.h b/src/cocoatweet/api/status/unretweet.h new file mode 100644 index 0000000..4f2421f --- /dev/null +++ b/src/cocoatweet/api/status/unretweet.h @@ -0,0 +1,18 @@ +#ifndef COCOATWEET_API_STATUS_UNRETWEET_H_ +#define COCOATWEET_API_STATUS_UNRETWEET_H_ + +#include +#include + +namespace CocoaTweet::API::Statuses { +class Unretweet : public CocoaTweet::API::Interface::HttpPost { +public: + Unretweet(); + + void id(const std::string& _id); + + CocoaTweet::API::Model::Tweet process(std::weak_ptr _oauth); +}; +} // namespace CocoaTweet::API::Statuses + +#endif From fc886b70b81e022eb3440be060efed9158e89d07 Mon Sep 17 00:00:00 2001 From: keita Date: Sat, 20 Mar 2021 10:26:53 +0900 Subject: [PATCH 10/13] =?UTF-8?q?statuses/unretweet/:id=E3=82=92=E5=8F=A9?= =?UTF-8?q?=E3=81=8F=E3=82=84=E3=81=A4=E3=82=92=E3=82=A8=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=83=AA=E3=83=BC=E3=83=9D=E3=82=A4=E3=83=B3=E3=83=88=E3=81=AB?= =?UTF-8?q?=E3=81=AE=E3=81=9B=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cocoatweet/api/status/status.cc | 7 +++++++ src/cocoatweet/api/status/status.h | 1 + 2 files changed, 8 insertions(+) diff --git a/src/cocoatweet/api/status/status.cc b/src/cocoatweet/api/status/status.cc index bf3a4c9..e2d261a 100644 --- a/src/cocoatweet/api/status/status.cc +++ b/src/cocoatweet/api/status/status.cc @@ -2,6 +2,7 @@ #include "cocoatweet/api/status/update.h" #include "cocoatweet/api/status/destroy.h" #include "cocoatweet/api/status/retweet.h" +#include "cocoatweet/api/status/unretweet.h" #include "cocoatweet/api/status/userTimeline.h" namespace CocoaTweet::API::Statuses { @@ -79,6 +80,12 @@ CocoaTweet::API::Model::Tweet Status::Retweet(const std::string& _id) const { return retweet.process(oauth_); } +CocoaTweet::API::Model::Tweet Status::Unretweet(const std::string& _id) const { + CocoaTweet::API::Statuses::Unretweet unretweet; + unretweet.id(_id); + return unretweet.process(oauth_); +} + std::vector Status::UserTimeline( const std::string& _screenName) const { CocoaTweet::API::Statuses::UserTimeline userTimeline; diff --git a/src/cocoatweet/api/status/status.h b/src/cocoatweet/api/status/status.h index 780772e..f4d7b7e 100644 --- a/src/cocoatweet/api/status/status.h +++ b/src/cocoatweet/api/status/status.h @@ -61,6 +61,7 @@ public: CocoaTweet::API::Model::Tweet Destroy(const std::string& _id) const; CocoaTweet::API::Model::Tweet Retweet(const std::string& _id) const; + CocoaTweet::API::Model::Tweet Unretweet(const std::string& _id) const; std::vector UserTimeline(const std::string& _screenName) const; From 6266d0f67c9a744c85683a429a524669ee4761eb Mon Sep 17 00:00:00 2001 From: keita Date: Sat, 20 Mar 2021 10:27:19 +0900 Subject: [PATCH 11/13] =?UTF-8?q?=E6=95=B4=E5=BD=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cocoatweet/api/status/userTimeline.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cocoatweet/api/status/userTimeline.h b/src/cocoatweet/api/status/userTimeline.h index d01d985..2da1b17 100644 --- a/src/cocoatweet/api/status/userTimeline.h +++ b/src/cocoatweet/api/status/userTimeline.h @@ -14,8 +14,8 @@ public: /// @brief primary constructor UserTimeline(); - /// @brief set screen name to get timeline - /// @param[in] const std::string& _screenName : screen name for getting tweet + /// @brief set screen name to get timeline + /// @param[in] const std::string& _screenName : screen name for getting tweet void screenName(const std::string& _screenName); /// @brief process request for endpoint From 783f0a40874f6a267fe959dc416b72c9516725b9 Mon Sep 17 00:00:00 2001 From: keita Date: Sat, 20 Mar 2021 10:29:12 +0900 Subject: [PATCH 12/13] manage README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 0f538db..45694cb 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ you can use these endpoint - statuses/update - statuses/destroy/:id - statuses/retweet/:id +- statuses/unretweet/:id - statuses/user_timeline - favorites/create - favorites/destroy @@ -125,6 +126,9 @@ api.status().Update("Upload media from Cocoa Twitter Library", std::vector Date: Sat, 20 Mar 2021 10:36:00 +0900 Subject: [PATCH 13/13] add LICENSE --- LICENSE | 7 +++++++ README.md | 1 + 2 files changed, 8 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1277b35 --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Copyright 2021 Keita.S(@milkcocoa0902) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 45694cb..f22ab7e 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ ![](http://jenkins.milkcocoa.info/job/CocoaTweet/job/master/badge/icon?style=plastic&config=unittest) ![](https://img.shields.io/badge/libcurl-libcurl4--openssl-blue) ![](https://img.shields.io/badge/libssl-1.1.1f-blue) +![](https://img.shields.io/badge/license-MIT-orange) # CocoaTweet This is a library for using Twitter API from C++