Merge branch 'develop' into main
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
commit
505a29bcb4
83
examples/example01_instance_info.cpp
Normal file
83
examples/example01_instance_info.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
/* This file is part of mastodonpp.
|
||||
* Copyright © 2020 tastytea <tastytea@tastytea.de>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
// Print information about an instance (/api/v1/instance).
|
||||
|
||||
#include <mastodonpp.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace masto = mastodonpp;
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::to_string;
|
||||
using std::string_view;
|
||||
using std::vector;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const vector<string_view> args(argv, argv + argc);
|
||||
if (args.size() <= 1)
|
||||
{
|
||||
cerr << "Usage: " << args[0] << " <instance hostname>\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Initialize an Instance.
|
||||
masto::Instance instance{args[1], {}};
|
||||
|
||||
// Get maximum allowed characters per post.
|
||||
const auto max_chars{instance.get_max_chars()};
|
||||
cout << "Maximum characters per post: " << max_chars << "\n\n";
|
||||
|
||||
// Initialize a Connection.
|
||||
masto::Connection connection{instance};
|
||||
|
||||
// Get information about the instance.
|
||||
masto::answer_type answer{connection.get(masto::API::v1::instance)};
|
||||
if (answer)
|
||||
{
|
||||
cout << answer << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (answer.curl_error_code == 0)
|
||||
{
|
||||
// If it is no libcurl error, it must be an HTTP error.
|
||||
cerr << "HTTP status: " << answer.http_status << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Network errors like “Couldn't resolve host.”.
|
||||
cerr << "libcurl error " << to_string(answer.curl_error_code)
|
||||
<< ": " << answer.error_message << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const masto::CURLException &e)
|
||||
{
|
||||
// Only libcurl errors that are not network errors will be thrown.
|
||||
// There went probably something wrong with the initialization.
|
||||
cerr << e.what() << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -302,7 +302,7 @@ public:
|
|||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
explicit API();
|
||||
explicit API(const endpoint_type &endpoint);
|
||||
|
||||
/*!
|
||||
* @brief Convert #endpoint_type to `std::string_view`.
|
||||
|
@ -310,14 +310,14 @@ public:
|
|||
* @since 0.1.0
|
||||
*/
|
||||
[[nodiscard]]
|
||||
inline string_view endpoint_to_string_view(const endpoint_type &endpoint)
|
||||
const
|
||||
inline string_view to_string_view() const
|
||||
{
|
||||
return _endpoint_map.at(endpoint).data();
|
||||
return _endpoint_map.at(_endpoint).data();
|
||||
}
|
||||
|
||||
private:
|
||||
const map<endpoint_type,string_view> _endpoint_map;
|
||||
const endpoint_type _endpoint;
|
||||
static const map<endpoint_type,string_view> _endpoint_map;
|
||||
};
|
||||
|
||||
} // namespace mastodonpp
|
||||
|
|
|
@ -74,7 +74,6 @@ public:
|
|||
private:
|
||||
Instance &_instance;
|
||||
const string_view _baseuri;
|
||||
const API _api;
|
||||
};
|
||||
|
||||
} // namespace mastodonpp
|
||||
|
|
|
@ -59,7 +59,8 @@ public:
|
|||
/*!
|
||||
* @brief Initializes curl and sets up connection.
|
||||
*
|
||||
* Calls `curl_global_init`, which is not thread-safe. For more information
|
||||
* The first time an instance of CURLWrapper is created, it calls
|
||||
* `curl_global_init`, which is not thread-safe. For more information
|
||||
* consult [curl_global_init(3)]
|
||||
* (https://curl.haxx.se/libcurl/c/curl_global_init.html).
|
||||
*
|
||||
|
|
|
@ -50,7 +50,8 @@ public:
|
|||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
explicit Instance(string hostname, string access_token);
|
||||
explicit Instance(const string_view &hostname,
|
||||
const string_view &access_token);
|
||||
|
||||
/*!
|
||||
* @brief Returns the hostname.
|
||||
|
@ -93,10 +94,7 @@ public:
|
|||
* @since 0.1.0
|
||||
*/
|
||||
[[nodiscard]]
|
||||
inline uint64_t get_max_chars() const
|
||||
{
|
||||
return _max_chars;
|
||||
}
|
||||
uint64_t get_max_chars();
|
||||
|
||||
private:
|
||||
const string _hostname;
|
||||
|
|
|
@ -70,7 +70,8 @@
|
|||
* @section exceptions Exceptions
|
||||
*
|
||||
* Any unrecoverable libcurl error will be thrown as a
|
||||
* mastodonpp::CURLException.
|
||||
* mastodonpp::CURLException. Network errors will **not** be thrown, but
|
||||
* reported via the return value.
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
|
10
src/api.cpp
10
src/api.cpp
|
@ -19,8 +19,11 @@
|
|||
namespace mastodonpp
|
||||
{
|
||||
|
||||
API::API()
|
||||
: _endpoint_map
|
||||
API::API(const endpoint_type &endpoint)
|
||||
: _endpoint{endpoint}
|
||||
{}
|
||||
|
||||
const map<API::endpoint_type,string_view> API::_endpoint_map
|
||||
{
|
||||
{v1::apps, "/api/v1/apps"},
|
||||
{v1::apps_verify_credentials, "/api/v1/apps/verify/credentials"},
|
||||
|
@ -238,7 +241,6 @@ API::API()
|
|||
"/api/pleroma/pleroma/notification_settings"},
|
||||
{pleroma::pleroma_healthcheck, "/api/pleroma/pleroma/healthcheck"},
|
||||
{pleroma::pleroma_change_email, "/api/pleroma/pleroma/change_email"},
|
||||
}
|
||||
{}
|
||||
};
|
||||
|
||||
} // namespace mastodonpp
|
||||
|
|
|
@ -22,14 +22,13 @@ namespace mastodonpp
|
|||
Connection::Connection(Instance &instance)
|
||||
: _instance{instance}
|
||||
, _baseuri{instance.get_baseuri()}
|
||||
, _api{}
|
||||
{}
|
||||
|
||||
answer_type Connection::get(const API::endpoint_type &endpoint)
|
||||
{
|
||||
return make_request(
|
||||
http_method::GET,
|
||||
string(_baseuri).append(_api.endpoint_to_string_view(endpoint)));
|
||||
string(_baseuri).append(API{endpoint}.to_string_view()));
|
||||
}
|
||||
|
||||
answer_type Connection::get(const string_view &endpoint)
|
||||
|
|
|
@ -26,17 +26,31 @@ namespace mastodonpp
|
|||
using std::uint8_t;
|
||||
using std::uint16_t;
|
||||
|
||||
static uint16_t curlwrapper_instances{0};
|
||||
|
||||
CURLWrapper::CURLWrapper()
|
||||
: _curl_buffer_error{}
|
||||
{
|
||||
if (curlwrapper_instances == 0)
|
||||
{
|
||||
curl_global_init(CURL_GLOBAL_ALL); // NOLINT(hicpp-signed-bitwise)
|
||||
}
|
||||
++curlwrapper_instances;
|
||||
debuglog << "CURLWrapper instances: " << curlwrapper_instances << " (+1)\n";
|
||||
|
||||
_connection = curl_easy_init();
|
||||
setup_curl();
|
||||
}
|
||||
CURLWrapper::~CURLWrapper() noexcept
|
||||
{
|
||||
curl_easy_cleanup(_connection);
|
||||
|
||||
--curlwrapper_instances;
|
||||
debuglog << "CURLWrapper instances: " << curlwrapper_instances << " (-1)\n";
|
||||
if (curlwrapper_instances == 0)
|
||||
{
|
||||
curl_global_cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
answer_type CURLWrapper::make_request(const http_method &method,
|
||||
|
|
|
@ -18,46 +18,60 @@
|
|||
#include "log.hpp"
|
||||
#include "return_types.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace mastodonpp
|
||||
{
|
||||
|
||||
using std::move;
|
||||
using std::stoull;
|
||||
|
||||
Instance::Instance(string hostname, string access_token)
|
||||
: _hostname{move(hostname)}
|
||||
Instance::Instance(const string_view &hostname, const string_view &access_token)
|
||||
: _hostname{hostname}
|
||||
, _baseuri{"https://" + _hostname}
|
||||
, _access_token{move(access_token)}
|
||||
, _max_chars{500}
|
||||
, _access_token{access_token}
|
||||
, _max_chars{0}
|
||||
{}
|
||||
|
||||
uint64_t Instance::get_max_chars()
|
||||
{
|
||||
constexpr uint64_t default_max_chars{500};
|
||||
|
||||
if (_max_chars == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
debuglog << "Querying " << _hostname << " for max_toot_chars…\n";
|
||||
const auto answer{make_request(http_method::GET,
|
||||
_baseuri + "/api/v1/instance")};
|
||||
if (answer)
|
||||
if (!answer)
|
||||
{
|
||||
debuglog << "Could not get instance info.\n";
|
||||
return default_max_chars;
|
||||
}
|
||||
|
||||
_max_chars = [&answer]
|
||||
{
|
||||
debuglog << "Querying instance for max_toot_chars…\n";
|
||||
auto &body{answer.body};
|
||||
size_t pos_start{body.find("max_toot_chars")};
|
||||
if (pos_start == string::npos)
|
||||
{
|
||||
debuglog << "max_toot_chars not found.";
|
||||
return;
|
||||
debuglog << "max_toot_chars not found.\n";
|
||||
return default_max_chars;
|
||||
}
|
||||
pos_start = body.find(':', pos_start) + 1;
|
||||
const size_t pos_end{body.find(',', pos_start)};
|
||||
|
||||
const auto max_toot_chars{body.substr(pos_start,
|
||||
pos_end - pos_start)};
|
||||
_max_chars = std::stoull(max_toot_chars);
|
||||
return static_cast<uint64_t>(stoull(max_toot_chars));
|
||||
}();
|
||||
debuglog << "Set _max_chars to: " << _max_chars << '\n';
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
debuglog << "Unexpected exception: " << e.what() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
return _max_chars;
|
||||
}
|
||||
|
||||
} // namespace mastodonpp
|
||||
|
|
20
src/log.hpp
20
src/log.hpp
|
@ -18,17 +18,35 @@
|
|||
#define MASTODONPP_LOG_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <string_view>
|
||||
|
||||
namespace mastodonpp
|
||||
{
|
||||
|
||||
using std::cerr;
|
||||
using std::string_view;
|
||||
|
||||
constexpr auto shorten_filename(const string_view &filename)
|
||||
{
|
||||
for (const string_view &dir : {"/src/", "/include/"})
|
||||
{
|
||||
auto pos{filename.rfind("/src/")};
|
||||
if (pos != string_view::npos)
|
||||
{
|
||||
return filename.substr(pos + dir.size());
|
||||
}
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
#define commonlog cerr << '[' << shorten_filename(__FILE__) \
|
||||
<< ':' << __LINE__ << ']'
|
||||
#ifndef NDEBUG
|
||||
#define debuglog cerr << "[" << __func__ << "():" << __LINE__ << "] DEBUG: "
|
||||
#define debuglog commonlog << " DEBUG: "
|
||||
#else
|
||||
#define debuglog false && cerr
|
||||
#endif
|
||||
#define errorlog commonlog << " ERROR: "
|
||||
|
||||
} // namespace mastodonpp
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user