Revamped streams.
This commit is contained in:
parent
ccedfba4af
commit
bde8d11706
|
@ -74,9 +74,11 @@ set_target_properties(mastodon-cpp PROPERTIES
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WITH_EASY)
|
if(WITH_EASY)
|
||||||
target_link_libraries(mastodon-cpp ${CURLPP_LIBRARIES} ${JSONCPP_LIBRARIES})
|
target_link_libraries(mastodon-cpp
|
||||||
|
${CURLPP_LIBRARIES} pthread ${JSONCPP_LIBRARIES})
|
||||||
else()
|
else()
|
||||||
target_link_libraries(mastodon-cpp ${CURLPP_LIBRARIES})
|
target_link_libraries(mastodon-cpp
|
||||||
|
${CURLPP_LIBRARIES} pthread)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Compile examples
|
# Compile examples
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
/* This file is part of mastodon-cpp.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Don't compile this if the Easy-interface is turned off
|
||||||
|
#ifndef WITHOUT_EASY
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <mutex>
|
||||||
|
#include <chrono>
|
||||||
|
#include <vector>
|
||||||
|
#ifdef MASTODON_CPP
|
||||||
|
#include "mastodon-cpp.hpp"
|
||||||
|
#include "easy/all.hpp"
|
||||||
|
#else
|
||||||
|
#include <mastodon-cpp/mastodon-cpp.hpp>
|
||||||
|
#include <mastodon-cpp/easy/all.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using std::cout;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::string;
|
||||||
|
using std::uint8_t;
|
||||||
|
using namespace Mastodon;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
std::cerr << "usage: " << argv[0] << " <instance>\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct a Mastodon::Easy object without authorization token.
|
||||||
|
Easy::API masto(argv[1], "");
|
||||||
|
// Prepare a pointer to the http object, to cancel the stream later.
|
||||||
|
std::unique_ptr<API::http> ptr;
|
||||||
|
// This variable is filled with the stream data.
|
||||||
|
string stream;
|
||||||
|
|
||||||
|
// Get the public timeline, the pointer is set here. The error detection is
|
||||||
|
// not very reliable at the moment, don't count on it.
|
||||||
|
uint8_t ret = masto.get_stream(API::v1::streaming_public, ptr, stream);
|
||||||
|
cout << "Return code: " << std::to_string(ret) << endl;
|
||||||
|
|
||||||
|
// Listen to the stream for 120 seconds.
|
||||||
|
for (uint8_t counter = 0; counter < 120; ++counter)
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
|
|
||||||
|
// Acquire lock for the stream variable to avoid simultaneous access.
|
||||||
|
std::lock_guard<std::mutex> lock(ptr->get_mutex());
|
||||||
|
// Parse event stream into a vector.
|
||||||
|
std::vector<Easy::stream_event> events = Easy::parse_stream(stream);
|
||||||
|
// Clear the stream buffer.
|
||||||
|
stream.clear();
|
||||||
|
|
||||||
|
for (const Easy::stream_event &event : events)
|
||||||
|
{
|
||||||
|
// Print out some information about the events.
|
||||||
|
switch (event.type)
|
||||||
|
{
|
||||||
|
case Easy::event_type::Update:
|
||||||
|
{
|
||||||
|
Easy::Status status(event.data);
|
||||||
|
cout << "[" << status.created_at().strtime("%T") << "] ";
|
||||||
|
cout << "Status from: " << status.account().acct()
|
||||||
|
<< " (" << status.url() << ")\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Easy::event_type::Notification:
|
||||||
|
{
|
||||||
|
Easy::Notification notification(event.data);
|
||||||
|
cout << "Notification involving: "
|
||||||
|
<< notification.account().acct()
|
||||||
|
<< " (" << notification.id() << ")\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Easy::event_type::Delete:
|
||||||
|
{
|
||||||
|
cout << "Deleted: " << event.data << '\n';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
cout << "Something undefined happened. 😱\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close connection.
|
||||||
|
ptr->cancel_stream();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#include <cstdio>
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::printf("mastodon-cpp was compiled without Easy support.\n");
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
#endif // WITHOUT_EASY
|
|
@ -21,9 +21,10 @@
|
||||||
using namespace Mastodon;
|
using namespace Mastodon;
|
||||||
using std::cerr;
|
using std::cerr;
|
||||||
|
|
||||||
return_call API::get_stream(const Mastodon::API::v1 &call,
|
uint8_t API::get_stream(const Mastodon::API::v1 &call,
|
||||||
const parametermap ¶meters,
|
const parametermap ¶meters,
|
||||||
std::unique_ptr<Mastodon::API::http> &ptr)
|
std::unique_ptr<Mastodon::API::http> &ptr,
|
||||||
|
string &stream)
|
||||||
{
|
{
|
||||||
string strcall = "";
|
string strcall = "";
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ return_call API::get_stream(const Mastodon::API::v1 &call,
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ttdebug << "ERROR: Invalid call.\n";
|
ttdebug << "ERROR: Invalid call.\n";
|
||||||
return { 22, "Invalid argument", 0, "" };
|
return 22;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,18 +56,19 @@ return_call API::get_stream(const Mastodon::API::v1 &call,
|
||||||
strcall += maptostr(parameters);
|
strcall += maptostr(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
return get_stream(strcall, ptr);
|
return get_stream(strcall, ptr, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_call API::get_stream(const Mastodon::API::v1 &call,
|
uint8_t API::get_stream(const Mastodon::API::v1 &call,
|
||||||
std::unique_ptr<Mastodon::API::http> &ptr)
|
std::unique_ptr<Mastodon::API::http> &ptr,
|
||||||
|
string &stream)
|
||||||
{
|
{
|
||||||
parametermap p = {};
|
return get_stream(call, {}, ptr, stream);
|
||||||
return get_stream(call, p, ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return_call API::get_stream(const std::string &call, std::unique_ptr<http> &ptr)
|
uint8_t API::get_stream(const std::string &call, std::unique_ptr<http> &ptr,
|
||||||
|
string &stream)
|
||||||
{
|
{
|
||||||
ptr = std::make_unique<http>(*this, _instance, _access_token);
|
ptr = std::make_unique<http>(*this, _instance, _access_token);
|
||||||
return ptr->request(http_method::GET_STREAM, call);
|
return ptr->request_stream(call, stream);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ const vector<Easy::stream_event> Easy::parse_stream(
|
||||||
else if (event.compare("delete") == 0)
|
else if (event.compare("delete") == 0)
|
||||||
type = event_type::Delete;
|
type = event_type::Delete;
|
||||||
|
|
||||||
vec.push_back(stream_event(type, data));
|
vec.push_back({ type, data });
|
||||||
stream = match.suffix().str();
|
stream = match.suffix().str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,11 @@ namespace Easy
|
||||||
*
|
*
|
||||||
* @since before 0.11.0
|
* @since before 0.11.0
|
||||||
*/
|
*/
|
||||||
typedef std::pair<event_type, string> stream_event;
|
typedef struct stream_event
|
||||||
|
{
|
||||||
|
event_type type = event_type::Undefined;
|
||||||
|
string data;
|
||||||
|
} stream_event;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Map of 'notification type' and 'push is requested or not'.
|
* @brief Map of 'notification type' and 'push is requested or not'.
|
||||||
|
|
38
src/http.cpp
38
src/http.cpp
|
@ -19,6 +19,7 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <cstring> // std::strncmp
|
#include <cstring> // std::strncmp
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <thread>
|
||||||
#include <curlpp/Options.hpp>
|
#include <curlpp/Options.hpp>
|
||||||
#include <curlpp/Exception.hpp>
|
#include <curlpp/Exception.hpp>
|
||||||
#include <curlpp/Infos.hpp>
|
#include <curlpp/Infos.hpp>
|
||||||
|
@ -49,13 +50,43 @@ return_call API::http::request(const http_method &meth, const string &path)
|
||||||
return request(meth, path, curlpp::Forms());
|
return request(meth, path, curlpp::Forms());
|
||||||
}
|
}
|
||||||
|
|
||||||
return_call API::http::request(const http_method &meth,
|
return_call API::http::request(const http_method &meth, const string &path,
|
||||||
const string &path,
|
|
||||||
const curlpp::Forms &formdata)
|
const curlpp::Forms &formdata)
|
||||||
|
{
|
||||||
|
string answer;
|
||||||
|
return request_common(meth, path, formdata, answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t API::http::request_stream(const string &path, string &stream)
|
||||||
|
{
|
||||||
|
static return_call ret;
|
||||||
|
_streamthread = std::thread(
|
||||||
|
[&]
|
||||||
|
{
|
||||||
|
ret = request_common(http_method::GET_STREAM, path,
|
||||||
|
curlpp::Forms(), stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
// FIXME: Build reliable error detection.
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
cancel_stream();
|
||||||
|
return ret.error_code;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return_call API::http::request_common(const http_method &meth,
|
||||||
|
const string &path,
|
||||||
|
const curlpp::Forms &formdata,
|
||||||
|
string &answer)
|
||||||
{
|
{
|
||||||
using namespace std::placeholders; // _1, _2, _3
|
using namespace std::placeholders; // _1, _2, _3
|
||||||
|
|
||||||
string answer;
|
|
||||||
ttdebug << "Path is: " << path << '\n';
|
ttdebug << "Path is: " << path << '\n';
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -220,6 +251,7 @@ double API::http::callback_progress(double /* dltotal */, double /* dlnow */,
|
||||||
void API::http::cancel_stream()
|
void API::http::cancel_stream()
|
||||||
{
|
{
|
||||||
_cancel_stream = true;
|
_cancel_stream = true;
|
||||||
|
_streamthread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::mutex &API::http::get_mutex()
|
std::mutex &API::http::get_mutex()
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <thread>
|
||||||
|
#include <cstdint>
|
||||||
#include <curlpp/cURLpp.hpp>
|
#include <curlpp/cURLpp.hpp>
|
||||||
#include <curlpp/Easy.hpp>
|
#include <curlpp/Easy.hpp>
|
||||||
|
|
||||||
|
@ -36,6 +38,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
using std::uint8_t;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @example example01_get_public_timeline.cpp
|
* @example example01_get_public_timeline.cpp
|
||||||
|
@ -92,8 +95,8 @@ namespace Mastodon
|
||||||
/*!
|
/*!
|
||||||
* @brief HTTP Request.
|
* @brief HTTP Request.
|
||||||
*
|
*
|
||||||
* @param meth A method defined in http::method
|
* @param meth A method defined in http::method.
|
||||||
* @param path The api call as string
|
* @param path The API call as string.
|
||||||
* @param formdata The form data for PATCH and POST requests.
|
* @param formdata The form data for PATCH and POST requests.
|
||||||
*
|
*
|
||||||
* @return @ref error "Error code". If the URL has permanently
|
* @return @ref error "Error code". If the URL has permanently
|
||||||
|
@ -105,6 +108,16 @@ namespace Mastodon
|
||||||
const string &path,
|
const string &path,
|
||||||
const curlpp::Forms &formdata);
|
const curlpp::Forms &formdata);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief HTTP Request for streams.
|
||||||
|
*
|
||||||
|
* @param path The API call as string.
|
||||||
|
* @param stream The stream of data that is returned.
|
||||||
|
*
|
||||||
|
* @since 0.100.0
|
||||||
|
*/
|
||||||
|
uint8_t request_stream(const string &path, string &stream);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Get all headers in a string
|
* @brief Get all headers in a string
|
||||||
*/
|
*/
|
||||||
|
@ -140,7 +153,12 @@ namespace Mastodon
|
||||||
string _headers;
|
string _headers;
|
||||||
bool _cancel_stream;
|
bool _cancel_stream;
|
||||||
std::mutex _mutex;
|
std::mutex _mutex;
|
||||||
|
std::thread _streamthread;
|
||||||
|
|
||||||
|
return_call request_common(const http_method &meth,
|
||||||
|
const string &path,
|
||||||
|
const curlpp::Forms &formdata,
|
||||||
|
string &answer);
|
||||||
size_t callback_write(char* data, size_t size, size_t nmemb,
|
size_t callback_write(char* data, size_t size, size_t nmemb,
|
||||||
string *oss);
|
string *oss);
|
||||||
double callback_progress(double /* dltotal */, double /* dlnow */,
|
double callback_progress(double /* dltotal */, double /* dlnow */,
|
||||||
|
@ -467,7 +485,7 @@ namespace Mastodon
|
||||||
*
|
*
|
||||||
* @param call A call defined in Mastodon::API::v1
|
* @param call A call defined in Mastodon::API::v1
|
||||||
*
|
*
|
||||||
* @return @ref error "Error code".
|
* @return return_call
|
||||||
*
|
*
|
||||||
* @since 0.100.0
|
* @since 0.100.0
|
||||||
*/
|
*/
|
||||||
|
@ -480,7 +498,7 @@ namespace Mastodon
|
||||||
* @param parameters A Mastodon::parametermap containing
|
* @param parameters A Mastodon::parametermap containing
|
||||||
* parameters
|
* parameters
|
||||||
*
|
*
|
||||||
* @return @ref error "Error code".
|
* @return return_call
|
||||||
*/
|
*/
|
||||||
const return_call get(const Mastodon::API::v1 &call,
|
const return_call get(const Mastodon::API::v1 &call,
|
||||||
const parametermap ¶meters);
|
const parametermap ¶meters);
|
||||||
|
@ -494,7 +512,7 @@ namespace Mastodon
|
||||||
* @param parameters A Mastodon::parametermap containing
|
* @param parameters A Mastodon::parametermap containing
|
||||||
* parameters
|
* parameters
|
||||||
*
|
*
|
||||||
* @return @ref error "Error code".
|
* @return return_call
|
||||||
*/
|
*/
|
||||||
const return_call get(const Mastodon::API::v2 &call,
|
const return_call get(const Mastodon::API::v2 &call,
|
||||||
const parametermap ¶meters);
|
const parametermap ¶meters);
|
||||||
|
@ -504,7 +522,7 @@ namespace Mastodon
|
||||||
*
|
*
|
||||||
* @param call String in the form `/api/v1/example`
|
* @param call String in the form `/api/v1/example`
|
||||||
*
|
*
|
||||||
* @return @ref error "Error code".
|
* @return return_call
|
||||||
*
|
*
|
||||||
* @since 0.100.0
|
* @since 0.100.0
|
||||||
*/
|
*/
|
||||||
|
@ -523,9 +541,10 @@ namespace Mastodon
|
||||||
*
|
*
|
||||||
* @since 0.100.0
|
* @since 0.100.0
|
||||||
*/
|
*/
|
||||||
return_call get_stream(const Mastodon::API::v1 &call,
|
uint8_t get_stream(const Mastodon::API::v1 &call,
|
||||||
const parametermap ¶meters,
|
const parametermap ¶meters,
|
||||||
std::unique_ptr<Mastodon::API::http> &ptr);
|
std::unique_ptr<Mastodon::API::http> &ptr,
|
||||||
|
string &stream);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Make a streaming GET request.
|
* @brief Make a streaming GET request.
|
||||||
|
@ -538,8 +557,9 @@ namespace Mastodon
|
||||||
*
|
*
|
||||||
* @since 0.100.0
|
* @since 0.100.0
|
||||||
*/
|
*/
|
||||||
return_call get_stream(const Mastodon::API::v1 &call,
|
uint8_t get_stream(const Mastodon::API::v1 &call,
|
||||||
std::unique_ptr<Mastodon::API::http> &ptr);
|
std::unique_ptr<Mastodon::API::http> &ptr,
|
||||||
|
string &stream);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Make a streaming GET request.
|
* @brief Make a streaming GET request.
|
||||||
|
@ -552,8 +572,9 @@ namespace Mastodon
|
||||||
*
|
*
|
||||||
* @since 0.100.0
|
* @since 0.100.0
|
||||||
*/
|
*/
|
||||||
return_call get_stream(const string &call,
|
uint8_t get_stream(const string &call,
|
||||||
std::unique_ptr<Mastodon::API::http> &ptr);
|
std::unique_ptr<Mastodon::API::http> &ptr,
|
||||||
|
string &stream);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Make a PATCH request.
|
* @brief Make a PATCH request.
|
||||||
|
|
Reference in New Issue