From 13a5e23a8be4082e1c2508a8a3abc6ab1dbf3729 Mon Sep 17 00:00:00 2001 From: tastytea Date: Wed, 24 Jan 2018 18:52:24 +0100 Subject: [PATCH] implemented PUT and DELETE, fixed argument encoding in POST --- CMakeLists.txt | 2 +- README.md | 14 +-- src/api_delete.cpp | 88 ++++++++++++++ src/api_post.cpp | 36 +++--- src/api_put.cpp | 54 +++++++++ src/examples/example6_toot_delete-toot.cpp | 63 ++++++++++ src/http_sync.cpp | 10 ++ src/mastodon-cpp.hpp | 127 +++++++++++++++++---- 8 files changed, 344 insertions(+), 50 deletions(-) create mode 100644 src/api_delete.cpp create mode 100644 src/api_put.cpp create mode 100644 src/examples/example6_toot_delete-toot.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index aa804a1..d145b4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 3.7) include(GNUInstallDirs) project (mastodon-cpp - VERSION 0.1.5 + VERSION 0.1.6 LANGUAGES CXX ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fPIC") diff --git a/README.md b/README.md index 52089fc..e666adb 100644 --- a/README.md +++ b/README.md @@ -89,8 +89,8 @@ If you use a debug build, you get more verbose error messages. * [x] Escape user input * [x] Implement all PATCH calls * [x] Implement all POST calls - * [ ] Implement all PUT calls - * [ ] Implement all DELETE calls + * [x] Implement all PUT calls + * [x] Implement all DELETE calls * Version 0.3.0 * [ ] Handle HTTP statuses 301 & 302 * [ ] Support registering as an application @@ -119,7 +119,7 @@ If you use a debug build, you get more verbose error messages. * [x] GET /api/v1/blocks * [x] GET /api/v1/domain_blocks * [x] POST /api/v1/domain_blocks - * [ ] DELETE /api/v1/domain_blocks + * [x] DELETE /api/v1/domain_blocks * [x] GET /api/v1/favourites * [x] GET /api/v1/follow_requests * [x] POST /api/v1/follow_requests/:id/authorize @@ -132,10 +132,10 @@ If you use a debug build, you get more verbose error messages. * [x] GET /api/v1/lists/:id/accounts * [x] GET /api/v1/lists/:id * [x] POST /api/v1/lists - * [ ] PUT /api/v1/lists/:id - * [ ] DELETE /api/v1/lists/:id + * [x] PUT /api/v1/lists/:id + * [x] DELETE /api/v1/lists/:id * [x] POST /api/v1/lists/:id/accounts - * [ ] DELETE /api/v1/lists/:id/accounts + * [x] DELETE /api/v1/lists/:id/accounts * [x] POST /api/v1/media * [x] GET /api/v1/mutes * [x] GET /api/v1/notifications @@ -151,7 +151,7 @@ If you use a debug build, you get more verbose error messages. * [x] GET /api/v1/statuses/:id/reblogged_by * [x] GET /api/v1/statuses/:id/favourited_by * [x] POST /api/v1/statuses - * [ ] DELETE /api/v1/statuses/:id + * [x] DELETE /api/v1/statuses/:id * [x] POST /api/v1/statuses/:id/reblog * [x] POST /api/v1/statuses/:id/unreblog * [x] POST /api/v1/statuses/:id/favourite diff --git a/src/api_delete.cpp b/src/api_delete.cpp new file mode 100644 index 0000000..d06d766 --- /dev/null +++ b/src/api_delete.cpp @@ -0,0 +1,88 @@ +/* This file is part of mastodon-cpp. + * Copyright © 2018 tastytea + * + * 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 . + */ + +#include +#include +#include +#include "macros.hpp" +#include "mastodon-cpp.hpp" + +using namespace Mastodon; +using std::string; + +const std::uint16_t API::del(const Mastodon::API::v1 &call, + const parametermap ¶meters) +{ + string strcall = ""; + + switch (call) + { + case v1::domain_blocks: + strcall = "/api/v1/domain_blocks"; + break; + default: + ttdebug << "ERROR: Invalid call.\n"; + return 1; + break; + } + + string answer; + return _http.request_sync(http::method::DELETE, strcall, + maptoformdata(parameters), answer); +} + +const std::uint16_t API::del(const Mastodon::API::v1 &call, + const string &argument) +{ + const parametermap p = {}; + return del(call, argument, p); +} +const std::uint16_t API::del(const Mastodon::API::v1 &call, + const string &argument, + const parametermap ¶meters) +{ + string strcall = ""; + const string argument_encoded = urlencode(argument); + + switch (call) + { + case v1::lists_id: + strcall = "/api/v1/lists/" + argument_encoded; + break; + case v1::lists_id_accounts: + strcall = "/api/v1/lists/" + argument_encoded + "/accounts"; + break; + case v1::statuses_id: + strcall = "/api/v1/statuses/" + argument_encoded; + break; + default: + ttdebug << "ERROR: Invalid call.\n"; + return 1; + break; + } + + string answer; + return _http.request_sync(http::method::DELETE, strcall, + maptoformdata(parameters), answer); +} + +const std::uint16_t API::del(const std::string &call, + const parametermap ¶meters, string &answer) +{ + + return _http.request_sync(http::method::DELETE, call, + maptoformdata(parameters), answer); +} diff --git a/src/api_post.cpp b/src/api_post.cpp index 381453a..2cfafc2 100644 --- a/src/api_post.cpp +++ b/src/api_post.cpp @@ -22,7 +22,7 @@ using namespace Mastodon; using std::string; -using std::cerr; + const std::uint16_t API::post(const Mastodon::API::v1 &call, string &answer) { const parametermap p; @@ -89,55 +89,55 @@ const std::uint16_t API::post(const Mastodon::API::v1 &call, switch (call) { case v1::accounts_id_follow: - strcall = "/api/v1/accounts/" + argument + "/follow"; + strcall = "/api/v1/accounts/" + argument_encoded + "/follow"; break; case v1::accounts_id_unfollow: - strcall = "/api/v1/accounts/" + argument + "/unfollow"; + strcall = "/api/v1/accounts/" + argument_encoded + "/unfollow"; break; case v1::accounts_id_block: - strcall = "/api/v1/accounts/" + argument + "/block"; + strcall = "/api/v1/accounts/" + argument_encoded + "/block"; break; case v1::accounts_id_unblock: - strcall = "/api/v1/accounts/" + argument + "/unblock"; + strcall = "/api/v1/accounts/" + argument_encoded + "/unblock"; break; case v1::accounts_id_mute: - strcall = "/api/v1/accounts/" + argument + "/mute"; + strcall = "/api/v1/accounts/" + argument_encoded + "/mute"; break; case v1::accounts_id_unmute: - strcall = "/api/v1/accounts/" + argument + "/unmute"; + strcall = "/api/v1/accounts/" + argument_encoded + "/unmute"; break; case v1::follow_requests_id_authorize: - strcall = "/api/v1/folow_requests/" + argument + "/authorize"; + strcall = "/api/v1/folow_requests/" + argument_encoded + "/authorize"; break; case v1::follow_requests_id_reject: - strcall = "/api/v1/folow_requests/" + argument + "/reject"; + strcall = "/api/v1/folow_requests/" + argument_encoded + "/reject"; break; case v1::lists_id_accounts: - strcall = "/api/v1/lists/" + argument + "/accounts"; + strcall = "/api/v1/lists/" + argument_encoded + "/accounts"; break; case v1::statuses_id_reblog: - strcall = "/api/v1/statuses/" + argument + "/reblog"; + strcall = "/api/v1/statuses/" + argument_encoded + "/reblog"; break; case v1::statuses_id_unreblog: - strcall = "/api/v1/statuses/" + argument + "/unreblog"; + strcall = "/api/v1/statuses/" + argument_encoded + "/unreblog"; break; case v1::statuses_id_favourite: - strcall = "/api/v1/statuses/" + argument + "/favourite"; + strcall = "/api/v1/statuses/" + argument_encoded + "/favourite"; break; case v1::statuses_id_unfavourite: - strcall = "/api/v1/statuses/" + argument + "/unfavourite"; + strcall = "/api/v1/statuses/" + argument_encoded + "/unfavourite"; break; case v1::statuses_id_pin: - strcall = "/api/v1/statuses/" + argument + "/pin"; + strcall = "/api/v1/statuses/" + argument_encoded + "/pin"; break; case v1::statuses_id_unpin: - strcall = "/api/v1/statuses/" + argument + "/unpin"; + strcall = "/api/v1/statuses/" + argument_encoded + "/unpin"; break; case v1::statuses_id_mute: - strcall = "/api/v1/statuses/" + argument + "/mute"; + strcall = "/api/v1/statuses/" + argument_encoded + "/mute"; break; case v1::statuses_id_unmute: - strcall = "/api/v1/statuses/" + argument + "/unmute"; + strcall = "/api/v1/statuses/" + argument_encoded + "/unmute"; break; default: ttdebug << "ERROR: Invalid call.\n"; diff --git a/src/api_put.cpp b/src/api_put.cpp new file mode 100644 index 0000000..713bdbf --- /dev/null +++ b/src/api_put.cpp @@ -0,0 +1,54 @@ +/* This file is part of mastodon-cpp. + * Copyright © 2018 tastytea + * + * 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 . + */ + +#include +#include +#include +#include "macros.hpp" +#include "mastodon-cpp.hpp" + +using namespace Mastodon; +using std::string; + +const std::uint16_t API::put(const Mastodon::API::v1 &call, + const string &argument, + const parametermap ¶meters, string &answer) +{ + string strcall = ""; + const string argument_encoded = urlencode(argument); + + switch (call) + { + case v1::lists_id: + strcall = "/api/v1/lists/" + argument_encoded; + break; + default: + ttdebug << "ERROR: Invalid call.\n"; + return 1; + break; + } + + return _http.request_sync(http::method::PUT, strcall, + maptoformdata(parameters), answer); +} + +const std::uint16_t API::put(const std::string &call, + const parametermap ¶meters, string &answer) +{ + + return _http.request_sync(http::method::PUT, call, + maptoformdata(parameters), answer); +} diff --git a/src/examples/example6_toot_delete-toot.cpp b/src/examples/example6_toot_delete-toot.cpp new file mode 100644 index 0000000..9dcec1b --- /dev/null +++ b/src/examples/example6_toot_delete-toot.cpp @@ -0,0 +1,63 @@ +/* This file is part of mastodon-cpp. + */ + +#include +#include +#include +#include +#include +#include +#include "../mastodon-cpp.hpp" + +using Mastodon::API; + +int main(int argc, char *argv[]) +{ + if (argc < 3) + { + std::cerr << "usage: " << argv[0] << " \n"; + return 1; + } + + Mastodon::API masto(argv[1], argv[2]); + masto.set_useragent("mastodon-cpp-example/1.3.3.7"); + std::string answer; + std::uint16_t ret; + std::string toot; + std::string id; + + std::cout << "Toot: "; + std::cin >> toot; + + API::parametermap parameters = + { + { "status", { toot } }, + { "visibility", { "unlisted" } }, + { "spoiler_text", { "test" } } + }; + ret = masto.post(API::v1::statuses, parameters, answer); + if (ret == 0) + { + id = answer.substr(7, answer.find("\"", 7) - 7); + + std::cout << "Deleting in 30 seconds...\n"; + std::this_thread::sleep_for(std::chrono::seconds(30)); + ret = masto.del(API::v1::statuses_id, id); + if (ret == 0) + { + std::cout << "Status " << id << " deleted.\n"; + } + else + { + std::cerr << "Error code: " << ret << '\n'; + return ret; + } + } + else + { + std::cerr << "Error code: " << ret << '\n'; + return ret; + } + + return 0; +} diff --git a/src/http_sync.cpp b/src/http_sync.cpp index 8489ac2..48637dc 100644 --- a/src/http_sync.cpp +++ b/src/http_sync.cpp @@ -98,15 +98,23 @@ const std::uint16_t API::http::request_sync(const method &meth, { case http::method::GET: request_stream << "GET"; + ttdebug << "Method is GET\n"; break; case http::method::PATCH: request_stream << "PATCH"; + ttdebug << "Method is PATCH\n"; break; case http::method::POST: request_stream << "POST"; + ttdebug << "Method is POST\n"; + break; + case http::method::PUT: + request_stream << "PUT"; + ttdebug << "Method is PUT\n"; break; case http::method::DELETE: request_stream << "DELETE"; + ttdebug << "Method is DELETE\n"; break; default: ttdebug << "ERROR: Not implemented\n"; @@ -129,6 +137,8 @@ const std::uint16_t API::http::request_sync(const method &meth, request_stream << formdata; break; case http::method::POST: + case http::method::PUT: + case http::method::DELETE: if (formdata.empty()) { request_stream << "\r\n"; diff --git a/src/mastodon-cpp.hpp b/src/mastodon-cpp.hpp index 69d19c5..dd9f2c3 100644 --- a/src/mastodon-cpp.hpp +++ b/src/mastodon-cpp.hpp @@ -52,7 +52,7 @@ class API { public: /*! - * @brief Used for passing optional parameters. + * @brief Used for passing (most of the time) optional parameters. * * Example: * @code @@ -196,11 +196,10 @@ public: /*! * @brief Make a GET request which doesn't require an argument, pass - * optional parameters. + * parameters. * * @param call A call defined in Mastodon::API::v1 - * @param parameters A Mastodon::API::parametermap containing optional - * parameters + * @param parameters A Mastodon::API::parametermap containing parameters * @param answer The answer from the server. Usually JSON. On error * an empty string. * @@ -211,13 +210,11 @@ public: std::string &answer); /*! - * @brief Make a GET request which requires an argument, pass optional - * parameters. + * @brief Make a GET request which requires an argument, pass parameters. * * @param call A call defined in Mastodon::API::v1 * @param argument The non-optional argument - * @param parameters A Mastodon::API::parametermap containing optional - * parameters + * @param parameters A Mastodon::API::parametermap containing parameters * @param answer The answer from the server. Usually JSON. On error * an empty string. * @@ -246,8 +243,7 @@ public: * Binary data must be base64-encoded. * * @param call A call defined in Mastodon::API::v1 - * @param parameters A Mastodon::API::parametermap containing optional - * parameters + * @param parameters A Mastodon::API::parametermap containing parameters * @param answer The answer from the server. Usually JSON. On error * an empty string. * @@ -255,7 +251,7 @@ public: */ const std::uint16_t patch(const Mastodon::API::v1 &call, const parametermap ¶meters, - std::string &answer); + std::string &answer); /*! * @brief Make a POST request which doesn't require an argument. @@ -266,7 +262,8 @@ public: * * @return @ref error "Error code". */ - const std::uint16_t post(const Mastodon::API::v1 &call, std::string &answer); + const std::uint16_t post(const Mastodon::API::v1 &call, + std::string &answer); /*! * @brief Make a POST request which requires an argument @@ -284,13 +281,12 @@ public: /*! * @brief Make a POST request which doesn't require an argument, pass - * optional parameters. + * parameters. * * Binary data must be base64-encoded. * * @param call A call defined in Mastodon::API::v1 - * @param parameters A Mastodon::API::parametermap containing optional - * parameters + * @param parameters A Mastodon::API::parametermap containing parameters * @param answer The answer from the server. Usually JSON. On error * an empty string. * @@ -301,24 +297,22 @@ public: std::string &answer); /*! - * @brief Make a POST request which requires an argument, pass optional - * parameters. + * @brief Make a POST request which requires an argument, pass parameters. * * Binary data must be base64-encoded. * * @param call A call defined in Mastodon::API::v1 * @param argument The non-optional argument - * @param parameters A Mastodon::API::parametermap containing optional - * parameters + * @param parameters A Mastodon::API::parametermap containing parameters * @param answer The answer from the server. Usually JSON. On error * an empty string. * * @return @ref error "Error code". */ const std::uint16_t post(const Mastodon::API::v1 &call, - const std::string &argument, - const parametermap ¶meters, - std::string &answer); + const std::string &argument, + const parametermap ¶meters, + std::string &answer); /*! * @brief Make a custom POST request. @@ -326,8 +320,7 @@ public: * Binary data must be base64-encoded. * * @param call String in the form `/api/v1/example` - * @param parameters A Mastodon::API::parametermap containing optional - * parameters + * @param parameters A Mastodon::API::parametermap containing parameters * @param answer The answer from the server. Usually JSON. On error * an empty string. * @@ -337,6 +330,91 @@ public: const parametermap ¶meters, std::string &answer); + /*! + * @brief Make a PUT request which requires an argument, pass parameters. + * + * @param call A call defined in Mastodon::API::v1 + * @param argument The non-optional argument + * @param parameters A Mastodon::API::parametermap containing + * parameters + * @param answer The answer from the server. Usually JSON. On error + * an empty string. + * + * @return @ref error "Error code". + */ + const std::uint16_t put(const Mastodon::API::v1 &call, + const std::string &argument, + const parametermap ¶meters, + std::string &answer); + + /*! + * @brief Make a custom PUT request. + * + * @param call String in the form `/api/v1/example` + * @param parameters A Mastodon::API::parametermap containing + * parameters + * @param answer The answer from the server. Usually JSON. On error + * an empty string. + * + * @return @ref error "Error code". + */ + const std::uint16_t put(const std::string &call, + const parametermap ¶meters, + std::string &answer); + + /*! + * @brief Make a DELETE request which requires an argument + * + * @param call A call defined in Mastodon::API::v1 + * @param argument The non-optional argument + * @param answer The answer from the server. Usually JSON. On error an + * empty string. + * + * @return @ref error "Error code". + */ + const std::uint16_t del(const Mastodon::API::v1 &call, + const std::string &argument); + + /*! + * @brief Make a DELETE request which doesn't require an argument, pass + * parameters. + * + * @param call A call defined in Mastodon::API::v1 + * @param parameters A Mastodon::API::parametermap containing parameters + * + * @return @ref error "Error code". + */ + const std::uint16_t del(const Mastodon::API::v1 &call, + const parametermap ¶meters); + + /*! + * @brief Make a DELETE request which requires an argument, pass + * parameters. + * + * @param call A call defined in Mastodon::API::v1 + * @param argument The non-optional argument + * @param parameters A Mastodon::API::parametermap containing parameters + * + * @return @ref error "Error code". + */ + const std::uint16_t del(const Mastodon::API::v1 &call, + const std::string &argument, + const parametermap ¶meters); + + /*! + * @brief Make a custom DELETE request. + * + * @param call String in the form `/api/v1/example` + * @param parameters A Mastodon::API::parametermap containing parameters + * @param answer The answer from the server. Usually JSON. On error + * an empty string. + * + * @return @ref error "Error code". + */ + const std::uint16_t del(const std::string &call, + const parametermap ¶meters, + std::string &answer); + private: const std::string _instance; const std::string _access_token; @@ -362,6 +440,7 @@ private: GET, PATCH, POST, + PUT, DELETE };