The first GET requests are working.

This commit is contained in:
tastytea 2018-01-09 22:12:11 +01:00
parent cd9b3f28d5
commit be6fca69fe
Signed by: tastytea
GPG Key ID: 59346E0EA35C67E5
9 changed files with 397 additions and 74 deletions

View File

@ -1,9 +1,9 @@
cmake_minimum_required (VERSION 3.7) cmake_minimum_required (VERSION 3.7)
project (mastodon-cpp project (mastodon-cpp
VERSION 0.0.0 VERSION 0.0.1
LANGUAGES CXX LANGUAGES CXX
) )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -rdynamic") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall")
# Write SHA1 hash and date of current git commit to a header file. Also version. # Write SHA1 hash and date of current git commit to a header file. Also version.
@ -38,7 +38,7 @@ set_target_properties(mastodon-cpp PROPERTIES
SOVERSION ${mastodon-cpp_VERSION_MAJOR} SOVERSION ${mastodon-cpp_VERSION_MAJOR}
) )
install(TARGETS mastodon-cpp DESTINATION lib) install(TARGETS mastodon-cpp DESTINATION lib)
#target_link_libraries(mastodon-cpp pthread boost_system boost_filesystem dl) target_link_libraries(mastodon-cpp pthread boost_system ssl crypto)
install(FILES ${PROJECT_SOURCE_DIR}/src/lib/mastodon-cpp.hpp DESTINATION include) install(FILES ${PROJECT_SOURCE_DIR}/src/lib/mastodon-cpp.hpp DESTINATION include)
# Example client # Example client
@ -59,19 +59,3 @@ if(NOT NOTESTS)
add_test(${bin} ${bin}) add_test(${bin} ${bin})
endforeach() endforeach()
endif() endif()
# Binary and source packages
# Some variables are not respected, it seems
# include(InstallRequiredSystemLibraries)
# set(CPACK_GENERATOR "TGZ")
# set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
# set(CPACK_PACKAGE_VERSION_MAJOR "${cdcl_VERSION_MAJOR}")
# set(CPACK_PACKAGE_VERSION_MINOR "${cdcl_VERSION_MINOR}")
# set(CPACK_PACKAGE_VERSION_PATCH "${cdcl_VERSION_PATCH}")
# set(CPACK_PACKAGE_DESCRIPTION_SUMMARY, "Edit checklists on CalDAV servers.")
# set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
# set(CPACK_PACKAGE_CHECKSUM, "SHA256")
# set(CPACK_SOURCE_PACKAGE_FILE_NAME, "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
# set(CPACK_SOURCE_IGNORE_FILES, "/\\\\.git/;/build/;.\\\\.sublime-")
# include (CPack)

View File

@ -1,4 +1,6 @@
**mastodon-cpp** is an interface for the Mastodon API. **mastodon-cpp** is a CPP wrapper for the Mastodon API. The aim is to be as simple as possible.
The library takes care of the network stuff. You submit a query and get the raw JSON.
All versions below 1.0.0 (SOVERSION 0) are considered insecure, unstable and can change drastically any time.
# Install # Install
## Dependencies ## Dependencies
@ -18,24 +20,39 @@
make make
# Usage # Usage
Mastodon::API masto("social.example.com", "access token");
std::cout << masto.get(Mastodon::API::v1::accounts_id, "12345") << '\n';
# Status of implementation There is an example in `src/example`.
* [ ] GET /api/v1/accounts/:id # TODO
* [ ] GET /api/v1/accounts/verify_credentials * Version 0.1.0
* [ ] Implement all GET methods
* [ ] Proper error handling
* [x] Network stuff
* Version 0.2.0
* [ ] Implement all PATCH methods
* [ ] Implement all POST methods
* [ ] Implement all DELETE methods
* Later
[ ] Escape user input
[ ] Asynchronous I/O
## Status of implementation
* [x] GET /api/v1/accounts/:id
* [x] GET /api/v1/accounts/verify_credentials
* [ ] PATCH /api/v1/accounts/update_credentials * [ ] PATCH /api/v1/accounts/update_credentials
* [ ] GET /api/v1/accounts/:id/followers * [x] GET /api/v1/accounts/:id/followers
* [ ] GET /api/v1/accounts/:id/following * [x] GET /api/v1/accounts/:id/following
* [ ] GET /api/v1/accounts/:id/statuses * [x] GET /api/v1/accounts/:id/statuses
* [ ] POST /api/v1/accounts/:id/follow * [ ] POST /api/v1/accounts/:id/follow
* [ ] POST /api/v1/accounts/:id/unfollow * [ ] POST /api/v1/accounts/:id/unfollow
* [ ] GET /api/v1/accounts/:id/block * [ ] POST /api/v1/accounts/:id/block
* [ ] GET /api/v1/accounts/:id/unblock * [ ] POST /api/v1/accounts/:id/unblock
* [ ] GET /api/v1/accounts/:id/mute * [ ] POST /api/v1/accounts/:id/mute
* [ ] GET /api/v1/accounts/:id/unmute * [ ] POST /api/v1/accounts/:id/unmute
* [ ] GET /api/v1/accounts/relationships * [x] GET /api/v1/accounts/relationships
* [ ] GET /api/v1/accounts/search * [x] GET /api/v1/accounts/search
* [ ] POST /api/v1/apps * [ ] POST /api/v1/apps
* [ ] GET /api/v1/blocks * [ ] GET /api/v1/blocks
* [ ] GET /api/v1/favourites * [ ] GET /api/v1/favourites
@ -69,7 +86,7 @@
* [ ] GET /api/v1/timelines/list/:list_id * [ ] GET /api/v1/timelines/list/:list_id
# Copyright # Copyright
Copyright © 2017 tastytea <tastytea@tastytea.de>. Copyright © 2018 tastytea <tastytea@tastytea.de>.
License GPLv3: GNU GPL version 3 <https://www.gnu.org/licenses/gpl-3.0.html>. License GPLv3: GNU GPL version 3 <https://www.gnu.org/licenses/gpl-3.0.html>.
This program comes with ABSOLUTELY NO WARRANTY. This is free software, This program comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions. and you are welcome to redistribute it under certain conditions.

95
src/api_get.cpp Normal file
View File

@ -0,0 +1,95 @@
/* This file is part of mastodon-cpp.
* Copyright © 2018 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <string>
#include <vector>
#include "mastodon-cpp.hpp"
using namespace Mastodon;
using std::string;
using std::cerr;
const string API::get(const Mastodon::API::v1 &method)
{
const std::vector<string> v{};
return get(method, v);
}
const string API::get(const Mastodon::API::v1 &method,
const std::vector<string> &parameters)
{
string strmethod = "";
switch (method)
{
case v1::accounts_verify_credentials:
strmethod = "/api/v1/accounts/verify_credentials";
break;
default:
cerr << "ERROR: Invalid method.\n";
break;
}
string answer;
_http.request_sync(http::method::GET, strmethod, answer);
return answer;
}
const string API::get(const Mastodon::API::v1 &method,
const string &argument)
{
const std::vector<string> v;
return get(method, argument, v);
}
const string API::get(const Mastodon::API::v1 &method,
const string &argument,
const std::vector<string> &parameters)
{
string strmethod = "";
switch (method)
{
case v1::accounts_id:
strmethod = "/api/v1/accounts/" + argument;
break;
case v1::accounts_id_followers:
strmethod = "/api/v1/accounts/" + argument + "/followers";
break;
case v1::accounts_id_following:
strmethod = "/api/v1/accounts/" + argument + "/following";
break;
case v1::accounts_id_statuses:
strmethod = "/api/v1/accounts/" + argument + "/statuses";
break;
case v1::accounts_relationships:
strmethod = "/api/v1/accounts/relationships?id=" + argument;
break;
case v1::accounts_search:
strmethod = "/api/v1/accounts/search?q=" + argument;
break;
default:
cerr << "ERROR: Invalid method.\n";
return "";
break;
}
string answer;
_http.request_sync(http::method::GET, strmethod, answer);
return answer;
}
const string API::get(const std::string &method)
{
return method;
}

View File

@ -1,22 +1,19 @@
/* This file is part of mastodon-cpp. /* This file is part of mastodon-cpp.
* Copyright © 2018 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <iostream>
#include "../mastodon-cpp.hpp" #include "../mastodon-cpp.hpp"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
// if (argc < 3)
{
std::cerr << "usage: " << argv[0] << " <instance> <access token>\n";
return 1;
}
Mastodon::API masto(argv[1], argv[2]);
std::cout << masto.get(Mastodon::API::v1::accounts_id,
"44897") << '\n';
} }

157
src/http.cpp Normal file
View File

@ -0,0 +1,157 @@
/* This file is part of mastodon-cpp.
* Copyright © 2018 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string>
#include <cstdint>
#include <iostream>
#include <istream>
#include <ostream>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include "mastodon-cpp.hpp"
using namespace Mastodon;
using std::string;
using std::cerr;
using boost::asio::ip::tcp;
namespace ssl = boost::asio::ssl;
typedef ssl::stream<tcp::socket> ssl_socket;
API::http::http(const string &instance, const string &access_token,
const string &useragent)
: _instance(instance)
, _access_token(access_token)
, _useragent(useragent)
, _ctx(ssl::context::tlsv12)
, _resolver(_io_service)
, _socket(_io_service, _ctx)
{
_ctx.set_options(ssl::context::tlsv12 | ssl::context::tlsv11 |
ssl::context::no_sslv3 | ssl::context::no_sslv2 |
ssl::context::no_tlsv1);
_ctx.set_default_verify_paths();
}
const std::uint16_t API::http::request_sync(const method &meth,
const string &path,
string &answer)
{
return request_sync(meth, path, "", answer);
}
const std::uint16_t API::http::request_sync(const method &meth,
const string &path,
const string &data,
string &answer)
{
try
{
tcp::resolver::query query(_instance, "https");
tcp::resolver::iterator endpoint_iterator = _resolver.resolve(query);
boost::asio::connect(_socket.lowest_layer(), endpoint_iterator);
_socket.lowest_layer().set_option(tcp::no_delay(true));
// Server Name Indication (SNI)
SSL_set_tlsext_host_name(_socket.native_handle(), _instance.c_str());
_socket.set_verify_mode(ssl::verify_peer);
_socket.set_verify_callback(ssl::rfc2818_verification(_instance));
_socket.handshake(ssl_socket::client);
boost::asio::streambuf request;
std::ostream request_stream(&request);
switch (meth)
{
case http::method::GET:
request_stream << "GET";
request_stream << " " << path;
break;
// case http::method::PATCH:
// request_stream << "PATCH";
// break;
// case http::method::POST:
// request_stream << "POST";
// break;
// case http::method::DELETE:
// request_stream << "DELETE";
// break;
default:
cerr << "NOT IMPLEMENTED\n";
return 0xffff;
}
request_stream << " HTTP/1.0\r\n";
request_stream << "Host: " << _instance << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n";
request_stream << "User-Agent: " << _useragent << "\r\n";
request_stream << "Authorization: Bearer "
<< _access_token << "\r\n\r\n";
boost::asio::write(_socket, request);
boost::asio::streambuf response;
boost::asio::read_until(_socket, response, "\r\n");
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
std::uint16_t status_code;
std::string status_message;
response_stream >> http_version;
response_stream >> status_code;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
cerr << "Invalid response\n";
return 0xffff;
}
if (status_code != 200)
{
cerr << "Response returned with status code " << status_code
<< ": " << status_message << "\n";
return 0xffff;
}
// Read headers
boost::asio::read_until(_socket, response, "\r\n\r\n");
std::string header;
while (std::getline(response_stream, header) && header != "\r")
{}
//response.consume(response.size());
// Read body
boost::system::error_code error;
answer = "";
std::ostringstream ss;
while (boost::asio::read(_socket, response,
boost::asio::transfer_at_least(1), error))
{
ss << &response;
}
if (error != boost::asio::error::eof)
{
throw boost::system::system_error(error);
}
answer = ss.str();
}
catch (const std::exception &e)
{
cerr << "Exception: " << e.what() << "\n";
return 0xffff;
}
return 0;
}

View File

@ -14,12 +14,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <iostream> #include <string>
#include "version.hpp"
#include "mastodon-cpp.hpp" #include "mastodon-cpp.hpp"
using std::cout; using namespace Mastodon;
using std::string;
Mastodon::Mastodon() API::API(const string &instance, const string &access_token)
: _instance(instance)
, _access_token(access_token)
, _useragent(string("mastodon-cpp/") + global::version)
, _http(instance, access_token, _useragent)
{ {
cout << "Test.\n"; //
}
const void API::set_useragent(const std::string &useragent)
{
_useragent = useragent;
} }

View File

@ -17,10 +17,81 @@
#ifndef MASTODON_CPP_HPP #ifndef MASTODON_CPP_HPP
#define MASTODON_CPP_HPP #define MASTODON_CPP_HPP
class Mastodon #include <string>
#include <vector>
#include <cstdint>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
namespace Mastodon
{ {
public: class API
Mastodon(); {
}; public:
enum class v1
{
accounts_id,
accounts_verify_credentials,
accounts_id_followers,
accounts_id_following,
accounts_id_statuses,
accounts_relationships,
accounts_search
};
explicit API(const std::string &instance,
const std::string &access_token);
// Select one of the predefined methods.
const std::string get(const Mastodon::API::v1 &method);
const std::string get(const Mastodon::API::v1 &method,
const std::vector<std::string> &parameters);
const std::string get(const Mastodon::API::v1 &method,
const std::string &argument,
const std::vector<std::string> &parameters);
const std::string get(const Mastodon::API::v1 &method,
const std::string &argument);
// Supply a custom method as string.
const std::string get(const std::string &method);
const void set_useragent(const std::string &useragent);
private:
const std::string _instance;
const std::string _access_token;
std::string _useragent;
class http
{
public:
enum class method
{
GET,
PATCH,
POST,
DELETE
};
explicit http(const std::string &instance,
const std::string &access_token,
const std::string &useragent);
const std::uint16_t request_sync(const method &meth,
const std::string &path,
std::string &answer);
const std::uint16_t request_sync(const method &meth,
const std::string &path,
const std::string &data,
std::string &answer);
private:
const std::string _instance;
const std::string _access_token;
const std::string _useragent;
boost::asio::ssl::context _ctx;
boost::asio::io_service _io_service;
boost::asio::ip::tcp::resolver _resolver;
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> _socket;
} _http;
};
}
#endif #endif

View File

@ -1,22 +1,9 @@
/* This file is part of mastodon-cpp. /* This file is part of mastodon-cpp.
* Copyright © 2018 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../mastodon-cpp.hpp" #include "../mastodon-cpp.hpp"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
Mastodon test; Mastodon::API test("", "");
} }

View File

@ -1,10 +1,14 @@
#ifndef VERSION_HPP #ifndef VERSION_HPP
#define VERSION_HPP #define VERSION_HPP
namespace global { namespace Mastodon
static constexpr char version[] = "@PROJECT_VERSION@"; {
static constexpr char git_sha1[] ="@GIT_SHA1@"; namespace global
static constexpr char git_date[] ="@GIT_DATE@"; {
static constexpr char version[] = "@PROJECT_VERSION@";
static constexpr char git_sha1[] ="@GIT_SHA1@";
static constexpr char git_date[] ="@GIT_DATE@";
}
} }
#endif // VERSION_HPP #endif // VERSION_HPP