Revamped streams.
This commit is contained in:
parent
ccedfba4af
commit
bde8d11706
|
@ -74,9 +74,11 @@ set_target_properties(mastodon-cpp PROPERTIES
|
|||
)
|
||||
|
||||
if(WITH_EASY)
|
||||
target_link_libraries(mastodon-cpp ${CURLPP_LIBRARIES} ${JSONCPP_LIBRARIES})
|
||||
target_link_libraries(mastodon-cpp
|
||||
${CURLPP_LIBRARIES} pthread ${JSONCPP_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(mastodon-cpp ${CURLPP_LIBRARIES})
|
||||
target_link_libraries(mastodon-cpp
|
||||
${CURLPP_LIBRARIES} pthread)
|
||||
endif()
|
||||
|
||||
# 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 std::cerr;
|
||||
|
||||
return_call API::get_stream(const Mastodon::API::v1 &call,
|
||||
const parametermap ¶meters,
|
||||
std::unique_ptr<Mastodon::API::http> &ptr)
|
||||
uint8_t API::get_stream(const Mastodon::API::v1 &call,
|
||||
const parametermap ¶meters,
|
||||
std::unique_ptr<Mastodon::API::http> &ptr,
|
||||
string &stream)
|
||||
{
|
||||
string strcall = "";
|
||||
|
||||
|
@ -46,7 +47,7 @@ return_call API::get_stream(const Mastodon::API::v1 &call,
|
|||
break;
|
||||
default:
|
||||
ttdebug << "ERROR: Invalid call.\n";
|
||||
return { 22, "Invalid argument", 0, "" };
|
||||
return 22;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -55,18 +56,19 @@ return_call API::get_stream(const Mastodon::API::v1 &call,
|
|||
strcall += maptostr(parameters);
|
||||
}
|
||||
|
||||
return get_stream(strcall, ptr);
|
||||
return get_stream(strcall, ptr, stream);
|
||||
}
|
||||
|
||||
return_call API::get_stream(const Mastodon::API::v1 &call,
|
||||
std::unique_ptr<Mastodon::API::http> &ptr)
|
||||
uint8_t API::get_stream(const Mastodon::API::v1 &call,
|
||||
std::unique_ptr<Mastodon::API::http> &ptr,
|
||||
string &stream)
|
||||
{
|
||||
parametermap p = {};
|
||||
return get_stream(call, p, ptr);
|
||||
return get_stream(call, {}, ptr, stream);
|
||||
}
|
||||
|
||||
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);
|
||||
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)
|
||||
type = event_type::Delete;
|
||||
|
||||
vec.push_back(stream_event(type, data));
|
||||
vec.push_back({ type, data });
|
||||
stream = match.suffix().str();
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,11 @@ namespace Easy
|
|||
*
|
||||
* @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'.
|
||||
|
|
38
src/http.cpp
38
src/http.cpp
|
@ -19,6 +19,7 @@
|
|||
#include <list>
|
||||
#include <cstring> // std::strncmp
|
||||
#include <exception>
|
||||
#include <thread>
|
||||
#include <curlpp/Options.hpp>
|
||||
#include <curlpp/Exception.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_call API::http::request(const http_method &meth,
|
||||
const string &path,
|
||||
return_call API::http::request(const http_method &meth, const string &path,
|
||||
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
|
||||
|
||||
string answer;
|
||||
ttdebug << "Path is: " << path << '\n';
|
||||
|
||||
try
|
||||
|
@ -220,6 +251,7 @@ double API::http::callback_progress(double /* dltotal */, double /* dlnow */,
|
|||
void API::http::cancel_stream()
|
||||
{
|
||||
_cancel_stream = true;
|
||||
_streamthread.join();
|
||||
}
|
||||
|
||||
std::mutex &API::http::get_mutex()
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <array>
|
||||
#include <mutex>
|
||||
#include <ostream>
|
||||
#include <thread>
|
||||
#include <cstdint>
|
||||
#include <curlpp/cURLpp.hpp>
|
||||
#include <curlpp/Easy.hpp>
|
||||
|
||||
|
@ -36,6 +38,7 @@
|
|||
#endif
|
||||
|
||||
using std::string;
|
||||
using std::uint8_t;
|
||||
|
||||
/*!
|
||||
* @example example01_get_public_timeline.cpp
|
||||
|
@ -92,8 +95,8 @@ namespace Mastodon
|
|||
/*!
|
||||
* @brief HTTP Request.
|
||||
*
|
||||
* @param meth A method defined in http::method
|
||||
* @param path The api call as string
|
||||
* @param meth A method defined in http::method.
|
||||
* @param path The API call as string.
|
||||
* @param formdata The form data for PATCH and POST requests.
|
||||
*
|
||||
* @return @ref error "Error code". If the URL has permanently
|
||||
|
@ -105,6 +108,16 @@ namespace Mastodon
|
|||
const string &path,
|
||||
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
|
||||
*/
|
||||
|
@ -140,7 +153,12 @@ namespace Mastodon
|
|||
string _headers;
|
||||
bool _cancel_stream;
|
||||
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,
|
||||
string *oss);
|
||||
double callback_progress(double /* dltotal */, double /* dlnow */,
|
||||
|
@ -467,7 +485,7 @@ namespace Mastodon
|
|||
*
|
||||
* @param call A call defined in Mastodon::API::v1
|
||||
*
|
||||
* @return @ref error "Error code".
|
||||
* @return return_call
|
||||
*
|
||||
* @since 0.100.0
|
||||
*/
|
||||
|
@ -480,7 +498,7 @@ namespace Mastodon
|
|||
* @param parameters A Mastodon::parametermap containing
|
||||
* parameters
|
||||
*
|
||||
* @return @ref error "Error code".
|
||||
* @return return_call
|
||||
*/
|
||||
const return_call get(const Mastodon::API::v1 &call,
|
||||
const parametermap ¶meters);
|
||||
|
@ -494,7 +512,7 @@ namespace Mastodon
|
|||
* @param parameters A Mastodon::parametermap containing
|
||||
* parameters
|
||||
*
|
||||
* @return @ref error "Error code".
|
||||
* @return return_call
|
||||
*/
|
||||
const return_call get(const Mastodon::API::v2 &call,
|
||||
const parametermap ¶meters);
|
||||
|
@ -504,7 +522,7 @@ namespace Mastodon
|
|||
*
|
||||
* @param call String in the form `/api/v1/example`
|
||||
*
|
||||
* @return @ref error "Error code".
|
||||
* @return return_call
|
||||
*
|
||||
* @since 0.100.0
|
||||
*/
|
||||
|
@ -523,9 +541,10 @@ namespace Mastodon
|
|||
*
|
||||
* @since 0.100.0
|
||||
*/
|
||||
return_call get_stream(const Mastodon::API::v1 &call,
|
||||
const parametermap ¶meters,
|
||||
std::unique_ptr<Mastodon::API::http> &ptr);
|
||||
uint8_t get_stream(const Mastodon::API::v1 &call,
|
||||
const parametermap ¶meters,
|
||||
std::unique_ptr<Mastodon::API::http> &ptr,
|
||||
string &stream);
|
||||
|
||||
/*!
|
||||
* @brief Make a streaming GET request.
|
||||
|
@ -538,8 +557,9 @@ namespace Mastodon
|
|||
*
|
||||
* @since 0.100.0
|
||||
*/
|
||||
return_call get_stream(const Mastodon::API::v1 &call,
|
||||
std::unique_ptr<Mastodon::API::http> &ptr);
|
||||
uint8_t get_stream(const Mastodon::API::v1 &call,
|
||||
std::unique_ptr<Mastodon::API::http> &ptr,
|
||||
string &stream);
|
||||
|
||||
/*!
|
||||
* @brief Make a streaming GET request.
|
||||
|
@ -552,8 +572,9 @@ namespace Mastodon
|
|||
*
|
||||
* @since 0.100.0
|
||||
*/
|
||||
return_call get_stream(const string &call,
|
||||
std::unique_ptr<Mastodon::API::http> &ptr);
|
||||
uint8_t get_stream(const string &call,
|
||||
std::unique_ptr<Mastodon::API::http> &ptr,
|
||||
string &stream);
|
||||
|
||||
/*!
|
||||
* @brief Make a PATCH request.
|
||||
|
|
Reference in New Issue