Merge pull request #9 from milkcocoa0902/develop
merge branch develop into master
This commit is contained in:
@@ -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.
|
||||||
@@ -2,6 +2,7 @@
|
|||||||

|

|
||||||

|

|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
# CocoaTweet
|
# CocoaTweet
|
||||||
This is a library for using Twitter API from C++
|
This is a library for using Twitter API from C++
|
||||||
@@ -11,6 +12,8 @@ you can use these endpoint
|
|||||||
- statuses/update
|
- statuses/update
|
||||||
- statuses/destroy/:id
|
- statuses/destroy/:id
|
||||||
- statuses/retweet/:id
|
- statuses/retweet/:id
|
||||||
|
- statuses/unretweet/:id
|
||||||
|
- statuses/user_timeline
|
||||||
- favorites/create
|
- favorites/create
|
||||||
- favorites/destroy
|
- favorites/destroy
|
||||||
- media/upload(support: jpg, jpeg, png, gif, mp4)
|
- media/upload(support: jpg, jpeg, png, gif, mp4)
|
||||||
@@ -124,6 +127,9 @@ api.status().Update("Upload media from Cocoa Twitter Library", std::vector<std::
|
|||||||
// Retweet a tweet
|
// Retweet a tweet
|
||||||
api.status().Retweet("tweet id");
|
api.status().Retweet("tweet id");
|
||||||
|
|
||||||
|
// un RT a tweet
|
||||||
|
api.status().Unretweet("tweet id")
|
||||||
|
|
||||||
// Delete a tweet
|
// Delete a tweet
|
||||||
api.status().Destroy("tweet id");
|
api.status().Destroy("tweet id");
|
||||||
|
|
||||||
@@ -132,6 +138,13 @@ api.favorite().Create("tweet id");
|
|||||||
|
|
||||||
// un Fav. a tweet
|
// un Fav. a tweet
|
||||||
api.favorite().Destroy("tweet id");
|
api.favorite().Destroy("tweet id");
|
||||||
|
|
||||||
|
// get a timeline with screen name
|
||||||
|
auto timeline = api.status().UserTimeline("milkcocoa0902");
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
donate by BitCoin : bc1qhpm8tmq72scqpl2ccemcf0ktfjg4rsu73e99tz
|
# More Information
|
||||||
|
See [API Document](https://cocoatweet.milkcocoa.info)
|
||||||
|
|
||||||
|
donate by BitCoin : bc1qhpm8tmq72scqpl2ccemcf0ktfjg4rsu73e99tz
|
||||||
|
|||||||
@@ -13,10 +13,9 @@ void Create::id(const std::string& _id) {
|
|||||||
|
|
||||||
CocoaTweet::API::Model::Tweet Create::process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth) {
|
CocoaTweet::API::Model::Tweet Create::process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth) {
|
||||||
CocoaTweet::API::Model::Tweet tweet;
|
CocoaTweet::API::Model::Tweet tweet;
|
||||||
HttpPost::process(_oauth,
|
HttpPost::process(_oauth, [&tweet](const std::string& _rcv) {
|
||||||
[&tweet](const unsigned int _responseCode, const std::string& _rcv) {
|
tweet = CocoaTweet::API::Model::Tweet(_rcv);
|
||||||
tweet = CocoaTweet::API::Model::Tweet(_responseCode, _rcv);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return tweet;
|
return tweet;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,9 @@ void Destroy::id(const std::string& _id) {
|
|||||||
CocoaTweet::API::Model::Tweet Destroy::process(
|
CocoaTweet::API::Model::Tweet Destroy::process(
|
||||||
std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth) {
|
std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth) {
|
||||||
CocoaTweet::API::Model::Tweet tweet;
|
CocoaTweet::API::Model::Tweet tweet;
|
||||||
HttpPost::process(_oauth,
|
HttpPost::process(_oauth, [&tweet](const std::string& _rcv) {
|
||||||
[&tweet](const unsigned int _responseCode, const std::string& _rcv) {
|
tweet = CocoaTweet::API::Model::Tweet(_rcv);
|
||||||
tweet = CocoaTweet::API::Model::Tweet(_responseCode, _rcv);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return tweet;
|
return tweet;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,8 @@ protected:
|
|||||||
std::map<std::string, std::string> bodyParam_;
|
std::map<std::string, std::string> bodyParam_;
|
||||||
std::string url_;
|
std::string url_;
|
||||||
std::string contentType_;
|
std::string contentType_;
|
||||||
virtual void process(
|
virtual void process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth,
|
||||||
std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth,
|
std::function<void(const std::string&)> _callback) = 0;
|
||||||
std::function<void(const unsigned int, const std::string&)> _callback) = 0;
|
|
||||||
static size_t curlCallback_(char* _ptr, size_t _size, size_t _nmemb, std::string* _stream) {
|
static size_t curlCallback_(char* _ptr, size_t _size, size_t _nmemb, std::string* _stream) {
|
||||||
int realsize = _size * _nmemb;
|
int realsize = _size * _nmemb;
|
||||||
_stream->append(_ptr, realsize);
|
_stream->append(_ptr, realsize);
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
#include <cocoatweet/api/interface/httpGet.h>
|
||||||
|
#include "cocoatweet/util/util.h"
|
||||||
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
extern "C" {
|
||||||
|
#include <curl/curl.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#include <iostream>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace CocoaTweet::API::Interface {
|
||||||
|
void HttpGet::process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth,
|
||||||
|
std::function<void(const std::string&)> _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<std::string> 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<std::string> 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(rcv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace CocoaTweet::API::Interface
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef COCOATWEET_API_INTERFACE_HTTPGET_H_
|
||||||
|
#define COCOATWEET_API_INTERFACE_HTTPGET_H_
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include "cocoatweet/oauth/oauth.h"
|
||||||
|
#include <cocoatweet/api/interface/httpBase.h>
|
||||||
|
|
||||||
|
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<CocoaTweet::OAuth::OAuth1> _oauth : pointer to OAuth object to
|
||||||
|
/// authenticate
|
||||||
|
/// @param[in] std::function<void(const unsigned int, const std::string&)> _callback :
|
||||||
|
/// callback method for processing to response
|
||||||
|
void process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth,
|
||||||
|
std::function<void(const std::string&)> _callback);
|
||||||
|
};
|
||||||
|
} // namespace CocoaTweet::API::Interface
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
#include <cocoatweet/api/interface/httpPost.h>
|
#include <cocoatweet/api/interface/httpPost.h>
|
||||||
#include "cocoatweet/util/util.h"
|
#include "cocoatweet/util/util.h"
|
||||||
|
#include <cocoatweet/exception/tweetNotFoundException.h>
|
||||||
|
#include <cocoatweet/exception/authenticateException.h>
|
||||||
|
#include <cocoatweet/exception/tweetDuplicateException.h>
|
||||||
|
#include <cocoatweet/exception/tweetTooLongException.h>
|
||||||
|
#include <cocoatweet/exception/rateLimitException.h>
|
||||||
|
#include "nlohmann/json.hpp"
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -15,7 +21,7 @@ extern "C" {
|
|||||||
|
|
||||||
namespace CocoaTweet::API::Interface {
|
namespace CocoaTweet::API::Interface {
|
||||||
void HttpPost::process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth,
|
void HttpPost::process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth,
|
||||||
std::function<void(const unsigned int, const std::string&)> _callback) {
|
std::function<void(const std::string&)> _callback) {
|
||||||
// エンドポイントへのパラメータにOAuthパラメータを付加して署名作成
|
// エンドポイントへのパラメータにOAuthパラメータを付加して署名作成
|
||||||
auto oauth = _oauth.lock();
|
auto oauth = _oauth.lock();
|
||||||
auto oauthParam = oauth->oauthParam();
|
auto oauthParam = oauth->oauthParam();
|
||||||
@@ -103,8 +109,29 @@ void HttpPost::process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth,
|
|||||||
exit(1);
|
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<int>() == 144) {
|
||||||
|
throw CocoaTweet::Exception::TweetNotFoundException(message.get<std::string>().c_str());
|
||||||
|
} else if (error.get<int>() == 32) {
|
||||||
|
throw CocoaTweet::Exception::AuthenticateException(message.get<std::string>().c_str());
|
||||||
|
} else if (error.get<int>() == 187) {
|
||||||
|
throw CocoaTweet::Exception::TweetDuplicateException(message.get<std::string>().c_str());
|
||||||
|
} else if (error.get<int>() == 88 || error.get<int>() == 185) {
|
||||||
|
throw CocoaTweet::Exception::RateLimitException(message.get<std::string>().c_str());
|
||||||
|
} else if (error.get<int>() == 186) {
|
||||||
|
throw CocoaTweet::Exception::TweetTooLongException(message.get<std::string>().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_callback) {
|
if (_callback) {
|
||||||
_callback(responseCode, rcv);
|
_callback(rcv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace CocoaTweet::API::Interface
|
} // namespace CocoaTweet::API::Interface
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ protected:
|
|||||||
/// @param[in] std::function<void(const unsigned int, const std::string&)> _callback :
|
/// @param[in] std::function<void(const unsigned int, const std::string&)> _callback :
|
||||||
/// callback method for processing to response
|
/// callback method for processing to response
|
||||||
void process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth,
|
void process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth,
|
||||||
std::function<void(const unsigned int, const std::string&)> _callback);
|
std::function<void(const std::string&)> _callback);
|
||||||
};
|
};
|
||||||
} // namespace CocoaTweet::API::Interface
|
} // namespace CocoaTweet::API::Interface
|
||||||
|
|
||||||
|
|||||||
@@ -43,10 +43,9 @@ CocoaTweet::API::Model::MediaStore Upload::process(
|
|||||||
bodyParam_.insert_or_assign(
|
bodyParam_.insert_or_assign(
|
||||||
"media_type", mimeType.at(std::filesystem::path(media_).extension().string<char>()));
|
"media_type", mimeType.at(std::filesystem::path(media_).extension().string<char>()));
|
||||||
|
|
||||||
HttpPost::process(_oauth,
|
HttpPost::process(_oauth, [&media](const std::string& _rcv) {
|
||||||
[&media](const unsigned int _responseCode, const std::string& _rsv) {
|
media = CocoaTweet::API::Model::MediaStore::parse(_rcv);
|
||||||
media = CocoaTweet::API::Model::MediaStore::parse(_responseCode, _rsv);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
bodyParam_.insert_or_assign("media_id", media.id());
|
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("command", "APPEND");
|
||||||
bodyParam_.insert_or_assign("segment_index", std::to_string(segment));
|
bodyParam_.insert_or_assign("segment_index", std::to_string(segment));
|
||||||
bodyParam_.insert_or_assign("media", data.substr(segment * chunk, chunk));
|
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;
|
// std::cout << _responseCode << std::endl << _rsv<< std::endl;
|
||||||
});
|
});
|
||||||
segment++;
|
segment++;
|
||||||
@@ -76,11 +75,9 @@ CocoaTweet::API::Model::MediaStore Upload::process(
|
|||||||
bodyParam_.insert_or_assign("command", "FINALIZE");
|
bodyParam_.insert_or_assign("command", "FINALIZE");
|
||||||
bodyParam_.erase("segment_index");
|
bodyParam_.erase("segment_index");
|
||||||
bodyParam_.erase("media");
|
bodyParam_.erase("media");
|
||||||
HttpPost::process(_oauth,
|
HttpPost::process(_oauth, [&media](const std::string& _rcv) {
|
||||||
[&media](const unsigned int _responseCode, const std::string& _rsv) {
|
media = CocoaTweet::API::Model::MediaStore::parse(_rcv);
|
||||||
std::cout << _responseCode << std::endl << _rsv << std::endl;
|
});
|
||||||
media = CocoaTweet::API::Model::MediaStore::parse(_responseCode, _rsv);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// STATUS if needed
|
// STATUS if needed
|
||||||
|
|||||||
@@ -3,31 +3,27 @@
|
|||||||
#include "nlohmann/json.hpp"
|
#include "nlohmann/json.hpp"
|
||||||
|
|
||||||
namespace CocoaTweet::API::Model {
|
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);
|
auto j = nlohmann::json::parse(_json);
|
||||||
MediaStore media;
|
MediaStore media;
|
||||||
|
|
||||||
if (_responseCode / 100 == 2) {
|
if (j.count("media_id_string") != 0) {
|
||||||
if (j.count("media_id_string") != 0) {
|
media.id(j["media_id_string"]);
|
||||||
media.id(j["media_id_string"]);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (j.count("size") != 0) {
|
if (j.count("size") != 0) {
|
||||||
media.size(j["size"]);
|
media.size(j["size"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j.count("expires_after_secs") != 0) {
|
if (j.count("expires_after_secs") != 0) {
|
||||||
media.expires(j["expires_after_secs"]);
|
media.expires(j["expires_after_secs"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j.count("processing_info") == 0) {
|
if (j.count("processing_info") == 0) {
|
||||||
media.state("succeeded");
|
media.state("succeeded");
|
||||||
} else {
|
|
||||||
media.state(j["processing_info"]["state"]);
|
|
||||||
media.remain(j["processing_info"]["check_after_secs"].get<unsigned int>());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
throw new CocoaTweet::Exception::Exception(j["error"]);
|
media.state(j["processing_info"]["state"]);
|
||||||
|
media.remain(j["processing_info"]["check_after_secs"].get<unsigned int>());
|
||||||
}
|
}
|
||||||
|
|
||||||
return media;
|
return media;
|
||||||
|
|||||||
@@ -15,18 +15,13 @@ public:
|
|||||||
MediaStore(const MediaStore&) = default;
|
MediaStore(const MediaStore&) = default;
|
||||||
|
|
||||||
/// @brief constructor for create object from json response
|
/// @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
|
/// @param[in] const std::string& _json : received content from twitter endpoint
|
||||||
MediaStore(const unsigned int _responseCode, const std::string& _json)
|
MediaStore(const std::string& _json) : MediaStore(MediaStore::parse(_json)) {}
|
||||||
: MediaStore(MediaStore::parse(_responseCode, _json)) {}
|
|
||||||
|
|
||||||
/// @brief response parser for MediaStore object
|
/// @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[in] const std::string& _json : received content from twitter endpoint
|
||||||
/// @param[out] CocoaTweet::API::Model::MediaStore
|
/// @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
|
/// @brief set id of tweet
|
||||||
/// @param[in] const std::string _id : media id to set
|
/// @param[in] const std::string _id : media id to set
|
||||||
|
|||||||
@@ -1,36 +1,15 @@
|
|||||||
#include <cocoatweet/api/model/tweet.h>
|
#include <cocoatweet/api/model/tweet.h>
|
||||||
#include <cocoatweet/exception/tweetNotFoundException.h>
|
|
||||||
#include <cocoatweet/exception/authenticateException.h>
|
|
||||||
#include <cocoatweet/exception/tweetDuplicateException.h>
|
|
||||||
#include <cocoatweet/exception/tweetTooLongException.h>
|
|
||||||
#include <cocoatweet/exception/rateLimitException.h>
|
|
||||||
#include "nlohmann/json.hpp"
|
#include "nlohmann/json.hpp"
|
||||||
|
|
||||||
namespace CocoaTweet::API::Model {
|
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);
|
auto j = nlohmann::json::parse(_json);
|
||||||
Tweet tweet;
|
Tweet tweet;
|
||||||
|
|
||||||
if (_responseCode == 200) {
|
tweet.id(j["id_str"]);
|
||||||
tweet.id(j["id_str"]);
|
tweet.createdAt(j["created_at"]);
|
||||||
tweet.createdAt(j["created_at"]);
|
tweet.text(j["text"]);
|
||||||
tweet.text(j["text"]);
|
tweet.source(j["source"]);
|
||||||
tweet.source(j["source"]);
|
|
||||||
} else {
|
|
||||||
auto error = j["errors"][0]["code"];
|
|
||||||
auto message = j["errors"][0]["message"];
|
|
||||||
if (error.get<int>() == 144) {
|
|
||||||
throw CocoaTweet::Exception::TweetNotFoundException(message.get<std::string>().c_str());
|
|
||||||
} else if (error.get<int>() == 32) {
|
|
||||||
throw CocoaTweet::Exception::AuthenticateException(message.get<std::string>().c_str());
|
|
||||||
} else if (error.get<int>() == 187) {
|
|
||||||
throw CocoaTweet::Exception::TweetDuplicateException(message.get<std::string>().c_str());
|
|
||||||
} else if (error.get<int>() == 88 || error.get<int>() == 185) {
|
|
||||||
throw CocoaTweet::Exception::RateLimitException(message.get<std::string>().c_str());
|
|
||||||
} else if (error.get<int>() == 186) {
|
|
||||||
throw CocoaTweet::Exception::TweetTooLongException(message.get<std::string>().c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return tweet;
|
return tweet;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,18 +15,13 @@ public:
|
|||||||
Tweet(const Tweet&) = default;
|
Tweet(const Tweet&) = default;
|
||||||
|
|
||||||
/// @brief constructor for create object from json response
|
/// @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
|
/// @param[in] const std::string& _json : received content from twitter endpoint
|
||||||
Tweet(const unsigned int _responseCode, const std::string& _json)
|
Tweet(const std::string& _json) : Tweet(Tweet::parse(_json)) {}
|
||||||
: Tweet(Tweet::parse(_responseCode, _json)) {}
|
|
||||||
|
|
||||||
/// @brief response parser for tweet object
|
/// @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[in] const std::string& _json : received content from twitter endpoint
|
||||||
/// @param[out] CocoaTweet::API::Model::Tweet
|
/// @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
|
/// @brief set id of tweet
|
||||||
/// @param[in] const std::string _id : tweet id to set
|
/// @param[in] const std::string _id : tweet id to set
|
||||||
|
|||||||
@@ -11,10 +11,9 @@ void Destroy::id(const std::string _id) {
|
|||||||
CocoaTweet::API::Model::Tweet Destroy::process(
|
CocoaTweet::API::Model::Tweet Destroy::process(
|
||||||
std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth) {
|
std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth) {
|
||||||
CocoaTweet::API::Model::Tweet tweet;
|
CocoaTweet::API::Model::Tweet tweet;
|
||||||
HttpPost::process(_oauth,
|
HttpPost::process(_oauth, [&tweet](const std::string& _rcv) {
|
||||||
[&tweet](const unsigned int _responseCode, const std::string& _rsv) {
|
tweet = CocoaTweet::API::Model::Tweet::parse(_rcv);
|
||||||
tweet = CocoaTweet::API::Model::Tweet::parse(_responseCode, _rsv);
|
});
|
||||||
});
|
|
||||||
return tweet;
|
return tweet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,20 +2,20 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace CocoaTweet::API::Statuses {
|
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";
|
contentType_ = "application/x-www-form-urlencoded";
|
||||||
url_ = "https://api.twitter.com/1.1/statuses/retweet/" + _id + ".json";
|
url_ = "https://api.twitter.com/1.1/statuses/retweet/" + _id + ".json";
|
||||||
}
|
}
|
||||||
|
|
||||||
CocoaTweet::API::Model::Tweet Retweet::process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth){
|
CocoaTweet::API::Model::Tweet Retweet::process(
|
||||||
|
std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth) {
|
||||||
CocoaTweet::API::Model::Tweet tweet;
|
CocoaTweet::API::Model::Tweet tweet;
|
||||||
HttpPost::process(_oauth,
|
HttpPost::process(_oauth, [&tweet](const std::string& _rcv) {
|
||||||
[&tweet](const unsigned int _responseCode, const std::string& _rcv) {
|
tweet = CocoaTweet::API::Model::Tweet(_rcv);
|
||||||
tweet = CocoaTweet::API::Model::Tweet(_responseCode, _rcv);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return tweet;
|
return tweet;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} // namespace CocoaTweet::API::Statuses
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
#include <cocoatweet/api/model/tweet.h>
|
#include <cocoatweet/api/model/tweet.h>
|
||||||
|
|
||||||
namespace CocoaTweet::API::Statuses {
|
namespace CocoaTweet::API::Statuses {
|
||||||
class Retweet : public CocoaTweet::API::Interface::HttpPost{
|
class Retweet : public CocoaTweet::API::Interface::HttpPost {
|
||||||
public:
|
public:
|
||||||
Retweet();
|
Retweet();
|
||||||
|
|
||||||
void id(const std::string& _id);
|
void id(const std::string& _id);
|
||||||
|
|
||||||
CocoaTweet::API::Model::Tweet process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth);
|
CocoaTweet::API::Model::Tweet process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth);
|
||||||
};
|
};
|
||||||
}
|
} // namespace CocoaTweet::API::Statuses
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
#include "cocoatweet/api/status/update.h"
|
#include "cocoatweet/api/status/update.h"
|
||||||
#include "cocoatweet/api/status/destroy.h"
|
#include "cocoatweet/api/status/destroy.h"
|
||||||
#include "cocoatweet/api/status/retweet.h"
|
#include "cocoatweet/api/status/retweet.h"
|
||||||
|
#include "cocoatweet/api/status/unretweet.h"
|
||||||
|
#include "cocoatweet/api/status/userTimeline.h"
|
||||||
|
|
||||||
namespace CocoaTweet::API::Statuses {
|
namespace CocoaTweet::API::Statuses {
|
||||||
Status::Status(std::shared_ptr<CocoaTweet::OAuth::OAuth1> _oauth) {
|
Status::Status(std::shared_ptr<CocoaTweet::OAuth::OAuth1> _oauth) {
|
||||||
@@ -72,9 +74,22 @@ CocoaTweet::API::Model::Tweet Status::Destroy(const std::string& _id) const {
|
|||||||
return destroy.process(oauth_);
|
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;
|
CocoaTweet::API::Statuses::Retweet retweet;
|
||||||
retweet.id(_id);
|
retweet.id(_id);
|
||||||
return retweet.process(oauth_);
|
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<CocoaTweet::API::Model::Tweet> Status::UserTimeline(
|
||||||
|
const std::string& _screenName) const {
|
||||||
|
CocoaTweet::API::Statuses::UserTimeline userTimeline;
|
||||||
|
userTimeline.screenName(_screenName);
|
||||||
|
return userTimeline.process(oauth_);
|
||||||
|
}
|
||||||
} // namespace CocoaTweet::API::Statuses
|
} // namespace CocoaTweet::API::Statuses
|
||||||
|
|||||||
@@ -61,6 +61,9 @@ public:
|
|||||||
CocoaTweet::API::Model::Tweet Destroy(const std::string& _id) const;
|
CocoaTweet::API::Model::Tweet Destroy(const std::string& _id) const;
|
||||||
|
|
||||||
CocoaTweet::API::Model::Tweet Retweet(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<CocoaTweet::API::Model::Tweet> UserTimeline(const std::string& _screenName) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Options defaultOpt_;
|
Options defaultOpt_;
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#include <cocoatweet/api/status/unretweet.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
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<CocoaTweet::OAuth::OAuth1> _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
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef COCOATWEET_API_STATUS_UNRETWEET_H_
|
||||||
|
#define COCOATWEET_API_STATUS_UNRETWEET_H_
|
||||||
|
|
||||||
|
#include <cocoatweet/api/interface/httpPost.h>
|
||||||
|
#include <cocoatweet/api/model/tweet.h>
|
||||||
|
|
||||||
|
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<CocoaTweet::OAuth::OAuth1> _oauth);
|
||||||
|
};
|
||||||
|
} // namespace CocoaTweet::API::Statuses
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -55,10 +55,9 @@ void Update::failDMCommands(bool _fail) {
|
|||||||
|
|
||||||
CocoaTweet::API::Model::Tweet Update::process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth) {
|
CocoaTweet::API::Model::Tweet Update::process(std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth) {
|
||||||
CocoaTweet::API::Model::Tweet tweet;
|
CocoaTweet::API::Model::Tweet tweet;
|
||||||
HttpPost::process(_oauth,
|
HttpPost::process(_oauth, [&tweet](const std::string& _rcv) {
|
||||||
[&tweet](const unsigned int _responseCode, const std::string& _rsv) {
|
tweet = CocoaTweet::API::Model::Tweet::parse(_rcv);
|
||||||
tweet = CocoaTweet::API::Model::Tweet::parse(_responseCode, _rsv);
|
});
|
||||||
});
|
|
||||||
return tweet;
|
return tweet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#include "cocoatweet/api/status/userTimeline.h"
|
||||||
|
#include <cocoatweet/util/util.h>
|
||||||
|
#include "nlohmann/json.hpp"
|
||||||
|
|
||||||
|
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<CocoaTweet::API::Model::Tweet> UserTimeline::process(
|
||||||
|
std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth) {
|
||||||
|
std::vector<CocoaTweet::API::Model::Tweet> tweet;
|
||||||
|
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(j.dump()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return tweet;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CocoaTweet::API::Statuses
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef COCOATWEET_API_STATUS_USERTIMELINE_H_
|
||||||
|
#define COCOATWEET_API_STATUS_USERTIMELINE_H_
|
||||||
|
|
||||||
|
#include <cocoatweet/api/interface/httpGet.h>
|
||||||
|
#include <cocoatweet/api/model/tweet.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <utility>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace CocoaTweet::API::Statuses {
|
||||||
|
/// @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<CocoaTweet::OAuth::OAuth1> _oauth : pointer to oauth object
|
||||||
|
/// @param[out] std::vector<CocoaTweet::API::Model::Tweet> : request result
|
||||||
|
std::vector<CocoaTweet::API::Model::Tweet> process(
|
||||||
|
std::weak_ptr<CocoaTweet::OAuth::OAuth1> _oauth);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string status_;
|
||||||
|
};
|
||||||
|
} // namespace CocoaTweet::API::Statuses
|
||||||
|
|
||||||
|
#endif
|
||||||
+1
-60
@@ -27,70 +27,11 @@ BOOST_AUTO_TEST_CASE(test02) {
|
|||||||
"source" : "Twitter for Android"
|
"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.id() == "1234567890");
|
||||||
BOOST_TEST(tweet.createdAt() == "Thu Mar 04 00:00:00 +0000 2021");
|
BOOST_TEST(tweet.createdAt() == "Thu Mar 04 00:00:00 +0000 2021");
|
||||||
BOOST_TEST(tweet.text() == "tweet");
|
BOOST_TEST(tweet.text() == "tweet");
|
||||||
BOOST_TEST(tweet.source() == "Twitter for Android");
|
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(401, 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(429, 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(403, 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(403, 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(403, json),
|
|
||||||
CocoaTweet::Exception::TweetDuplicateException);
|
|
||||||
}
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|||||||
Reference in New Issue
Block a user