From 4d5b331a0fb99d4a1eef3a45e4eea9cd23548052 Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 19 Sep 2019 23:20:19 +0200 Subject: [PATCH 01/11] Removed /api/v1/search. Because it is not documented by tootsuite anymore. --- src/api/get.cpp | 5 ----- src/mastodon-cpp.hpp | 10 ++++++---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/api/get.cpp b/src/api/get.cpp index 5ce5fed..92dfc0f 100644 --- a/src/api/get.cpp +++ b/src/api/get.cpp @@ -151,11 +151,6 @@ const return_call API::get(const Mastodon::API::v1 &call, strcall = "/api/v1/notifications/" + strid; break; } - case v1::search: - { - strcall = "/api/v1/search"; - break; - } case v1::statuses_id: { strcall = "/api/v1/statuses/" + strid; diff --git a/src/mastodon-cpp.hpp b/src/mastodon-cpp.hpp index 6e06235..b70f846 100644 --- a/src/mastodon-cpp.hpp +++ b/src/mastodon-cpp.hpp @@ -226,8 +226,8 @@ namespace Mastodon lists, accounts_id_lists, - lists_id, lists_id_accounts, + lists_id, media, media_id, @@ -244,19 +244,20 @@ namespace Mastodon notifications_dismiss, push_subscription, + // polls_id, + // polls_id_votes, + reports, // scheduled_statuses, // scheduled_statuses_id, - search, - - statuses, statuses_id, statuses_id_context, statuses_id_card, statuses_id_reblogged_by, statuses_id_favourited_by, + statuses, statuses_id_reblog, statuses_id_unreblog, statuses_id_pin, @@ -268,6 +269,7 @@ namespace Mastodon timelines_tag_hashtag, timelines_list_list_id, + // streaming_health, streaming_user, streaming_public, streaming_public_local, From 416675a6673392dddc0dd8d08dafc45c00815871 Mon Sep 17 00:00:00 2001 From: tastytea Date: Fri, 20 Sep 2019 00:07:17 +0200 Subject: [PATCH 02/11] Added Entity Easy::Poll. --- README.adoc | 9 +++- src/easy/entities/poll.cpp | 86 +++++++++++++++++++++++++++++++ src/easy/entities/poll.hpp | 98 ++++++++++++++++++++++++++++++++++++ src/easy/types_easy.hpp | 9 ++++ tests/entities/test_poll.cpp | 94 ++++++++++++++++++++++++++++++++++ 5 files changed, 294 insertions(+), 2 deletions(-) create mode 100644 src/easy/entities/poll.cpp create mode 100644 src/easy/entities/poll.hpp create mode 100644 tests/entities/test_poll.cpp diff --git a/README.adoc b/README.adoc index fbc5408..29ca70e 100644 --- a/README.adoc +++ b/README.adoc @@ -97,7 +97,12 @@ Not included in this list are entities. * `Mastodon::Easy::alert_type`, used for push subscriptions. * `Mastodon::Easy::time_type`: Type for time, can be converted to `time_point` and `string`. -* `Mastodon::Easy::Account::account_field_type`: Type for fields in accounts. +* `Mastodon::Easy::account_field_type`: Type for fields in accounts. +* `Mastodon::Easy::urls_type`: Type for URLs returned by `Instance::urls()`. +* `Mastodon::Easy::stats_type`: Type for statistics returned by + `Instance::stats()`. +* `Mastodon::Easy::poll_options_type`: Type for poll options returned by + `Poll::options()`. === Error codes @@ -392,7 +397,7 @@ strings and you can use unsupported fields in an `Entity` by converting it to * [x] List * [x] Mention * [x] Notification -* [ ] Poll +* [x] Poll * [x] PushSubscription * [x] Relationship * [ ] Report ^(Deprecated)^ diff --git a/src/easy/entities/poll.cpp b/src/easy/entities/poll.cpp new file mode 100644 index 0000000..3b18a68 --- /dev/null +++ b/src/easy/entities/poll.cpp @@ -0,0 +1,86 @@ +/* This file is part of mastodon-cpp. + * Copyright © 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "poll.hpp" +#include "debug.hpp" + +using namespace Mastodon; +using Poll = Easy::Poll; + +bool Poll::valid() const +{ + return Entity::check_valid( + { + "id", + "expired", + "expired", + "multiple", + "votes_count", + "options" + }); +} + +const string Poll::id() const +{ + return get_string("id"); +} + +const Easy::time_type Poll::expires_at() const +{ + return get_time("expires_at"); +} + +bool Poll::expired() const +{ + return get_bool("expired"); +} + +bool Poll::multiple() const +{ + return get_bool("multiple"); +} + +uint64_t Poll::votes_count() const +{ + return get_uint64("votes_count"); +} + +const vector Poll::options() const +{ + const Json::Value &node = get("options"); + + if (node.isArray()) + { + vector vec_options; + std::transform(node.begin(), node.end(), std::back_inserter(vec_options), + [](const Json::Value &value) + { + return Easy::poll_options_type( + { + value["title"].asString(), + value["votes_count"].asUInt64() + }); + }); + return vec_options; + } + + return {}; +} + +bool Poll::voted() const +{ + return get_bool("voted"); +} diff --git a/src/easy/entities/poll.hpp b/src/easy/entities/poll.hpp new file mode 100644 index 0000000..61b2558 --- /dev/null +++ b/src/easy/entities/poll.hpp @@ -0,0 +1,98 @@ +/* This file is part of mastodon-cpp. + * Copyright © 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef MASTODON_CPP_EASY_POLL_HPP +#define MASTODON_CPP_EASY_POLL_HPP + +#include +#include +#include + +#include "../../mastodon-cpp.hpp" +#include "../entity.hpp" + +using std::string; +using std::uint64_t; + +namespace Mastodon +{ +namespace Easy +{ + /*! + * @brief Class to hold polls. + * + * @since 0.107.0 + */ + class Poll : public Entity + { + public: + using Entity::Entity; + + virtual bool valid() const override; + + /*! + * @brief Returns poll ID. + * + * @since 0.107.0 + */ + const string id() const; + + /*! + * @brief Returns time when the poll expires. + * + * @since 0.107.0 + */ + const Easy::time_type expires_at() const; + + /*! + * @brief Returns true if poll has expired. + * + * @since 0.107.0 + */ + bool expired() const; + + /*! + * @brief Returns true or false. + * + * @since 0.107.0 + */ + bool multiple() const; + + /*! + * @brief Returns the number of votes. + * + * @since 0.107.0 + */ + uint64_t votes_count() const; + + /*! + * @brief Returns poll options and their votes count. + * + * @since 0.107.0 + */ + const vector options() const; + + /*! + * @brief Returns whether you voted or not. + * + * @since 0.107.0 + */ + bool voted() const; + }; +} +} + +#endif // MASTODON_CPP_EASY_POLL_HPP diff --git a/src/easy/types_easy.hpp b/src/easy/types_easy.hpp index f87be58..1591e5d 100644 --- a/src/easy/types_easy.hpp +++ b/src/easy/types_easy.hpp @@ -224,6 +224,15 @@ namespace Easy uint64_t status_count = 0; uint64_t domain_count = 0; } stats_type; + + /*! + * @brief Poll options returned by Poll::options(). + */ + typedef struct poll_options_type + { + string title; + uint64_t votes_count = 0; + } poll_options_type; } } #endif // MASTODON_CPP_EASY_TYPES_EASY_HPP diff --git a/tests/entities/test_poll.cpp b/tests/entities/test_poll.cpp new file mode 100644 index 0000000..620b792 --- /dev/null +++ b/tests/entities/test_poll.cpp @@ -0,0 +1,94 @@ +/* This file is part of mastodon-cpp. + * Copyright © 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include "easy/entities/poll.hpp" +#include "easy/easy.hpp" + +using std::string; +using std::chrono::system_clock; + +using namespace Mastodon; + +SCENARIO ("Easy::Poll works as intended", "[entity]") +{ + GIVEN ("An Easy::Poll object") + { + Easy::Poll poll; + bool exception = false; + + WHEN ("It is initialized with valid poll data") + { + const string data = + "{\"emojis\":[]," + "\"expired\":false," + "\"expires_at\":\"2019-09-22T12:48:19.000Z\"," + "\"id\":\"1234567\"," + "\"multiple\":false," + "\"options\":[" + "{\"title\":\"Yes\"," "\"votes_count\":12}," + "{\"title\":\"No\",\"votes_count\":13}]," + "\"voted\":false," + "\"votes_count\":25}"; + + try + { + poll.from_string(data); + } + catch (const std::exception &e) + { + exception = true; + } + + THEN ("No exception is thrown") + AND_THEN ("Poll is valid") + AND_THEN ("The attributes are set to the right values") + { + REQUIRE_FALSE(exception); + REQUIRE(poll.valid()); + REQUIRE(poll.id() == "1234567"); + REQUIRE(poll.expired() == false); + REQUIRE(poll.options().size() == 2); + REQUIRE(poll.options()[1].votes_count == 13); + } + } + + WHEN ("It is initialized with an empty string") + { + try + { + poll.from_string(""); + } + catch (const std::exception &e) + { + exception = true; + } + + THEN ("No exception is thrown") + AND_THEN ("It is not valid") + AND_THEN ("id is empty") + { + REQUIRE_FALSE(exception); + REQUIRE_FALSE(poll.valid()); + REQUIRE(poll.id() == ""); + REQUIRE(poll.options().size() == 0); + } + } + } +} From 1b514df5550265b0e5bcdd5b2f502b1ead4ffa61 Mon Sep 17 00:00:00 2001 From: tastytea Date: Fri, 20 Sep 2019 00:40:22 +0200 Subject: [PATCH 03/11] Added /api/v1/polls/:id and /api/v1/polls/:id/votes. --- README.adoc | 4 +- src/api/get.cpp | 5 ++ src/api/post.cpp | 5 ++ src/easy/return_types_easy.cpp | 2 + src/mastodon-cpp.hpp | 4 +- tests/api/test_api_v1_polls_id.cpp | 76 ++++++++++++++++++++++ tests/api/test_api_v1_polls_id_votes.cpp | 80 ++++++++++++++++++++++++ 7 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 tests/api/test_api_v1_polls_id.cpp create mode 100644 tests/api/test_api_v1_polls_id_votes.cpp diff --git a/README.adoc b/README.adoc index 29ca70e..ebb6cb7 100644 --- a/README.adoc +++ b/README.adoc @@ -343,8 +343,8 @@ strings and you can use unsupported fields in an `Entity` by converting it to ** [x] PUT /api/v1/push/subscription ** [x] DELETE /api/v1/push/subscription * Polls - ** [ ] GET /api/v1/polls/:id - ** [ ] POST /api/v1/polls/:id/votes + ** [x] GET /api/v1/polls/:id + ** [x] POST /api/v1/polls/:id/votes * Reports ** [x] GET /api/v1/reports ^(Deprecated)^ ** [x] POST /api/v1/reports diff --git a/src/api/get.cpp b/src/api/get.cpp index 92dfc0f..38c74eb 100644 --- a/src/api/get.cpp +++ b/src/api/get.cpp @@ -231,6 +231,11 @@ const return_call API::get(const Mastodon::API::v1 &call, strcall = "/api/v1/suggestions"; break; } + case v1::polls_id: + { + strcall = "/api/v1/polls/" + strid; + break; + } default: { ttdebug << "ERROR: Invalid argument.\n"; diff --git a/src/api/post.cpp b/src/api/post.cpp index fed3d55..576f708 100644 --- a/src/api/post.cpp +++ b/src/api/post.cpp @@ -195,6 +195,11 @@ return_call API::post(const Mastodon::API::v1 &call, strcall = "/api/v1/filters"; break; } + case v1::polls_id_votes: + { + strcall = "/api/v1/polls/" + strid + "/votes"; + break; + } default: { ttdebug << "ERROR: Invalid argument.\n"; diff --git a/src/easy/return_types_easy.cpp b/src/easy/return_types_easy.cpp index 8204e36..e9f8af9 100644 --- a/src/easy/return_types_easy.cpp +++ b/src/easy/return_types_easy.cpp @@ -33,6 +33,7 @@ #include "easy/entities/token.hpp" #include "easy/entities/pushsubscription.hpp" #include "easy/entities/filter.hpp" +#include "easy/entities/poll.hpp" using namespace Mastodon; @@ -92,6 +93,7 @@ template struct Easy::return_entity; template struct Easy::return_entity; template struct Easy::return_entity; template struct Easy::return_entity; +template struct Easy::return_entity; template diff --git a/src/mastodon-cpp.hpp b/src/mastodon-cpp.hpp index b70f846..0a7bb51 100644 --- a/src/mastodon-cpp.hpp +++ b/src/mastodon-cpp.hpp @@ -244,8 +244,8 @@ namespace Mastodon notifications_dismiss, push_subscription, - // polls_id, - // polls_id_votes, + polls_id, + polls_id_votes, reports, diff --git a/tests/api/test_api_v1_polls_id.cpp b/tests/api/test_api_v1_polls_id.cpp new file mode 100644 index 0000000..908cb98 --- /dev/null +++ b/tests/api/test_api_v1_polls_id.cpp @@ -0,0 +1,76 @@ +/* This file is part of mastodon-cpp. + * Copyright © 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include "mastodon-cpp.hpp" +#include "easy/easy.hpp" +#include "easy/entities/poll.hpp" +#include "../environment_variables.hpp" + +using namespace Mastodon; + +SCENARIO ("/api/v1/polls/:id can be called successfully", + "[api][auth][mastodon][pleroma][glitch-soc]") +{ + REQUIRE (access_token != nullptr); + + GIVEN ("instance = " + instance) + { + Mastodon::Easy::API masto(instance, access_token); + return_call ret; + Easy::Poll poll; + bool exception = false; + + WHEN ("GET /api/v1/polls/:id is called") + { + try + { + ret = masto.get(API::v1::polls_id, + {{ "id", { "4823515" } }}); + if (ret.answer == "[]") + { + WARN("Poll not found."); + } + else + { + poll.from_string(ret.answer); + } + } + catch (const std::exception &e) + { + exception = true; + WARN(e.what()); + } + + THEN("No exception is thrown") + AND_THEN ("No errors are returned") + AND_THEN ("Answer is valid") + AND_THEN ("The answer makes sense") + { + REQUIRE_FALSE(exception); + + REQUIRE(ret.error_code == 0); + REQUIRE(ret.http_error_code == 200); + REQUIRE(poll.valid()); + + REQUIRE(poll.id() != ""); + } + } + } +} + diff --git a/tests/api/test_api_v1_polls_id_votes.cpp b/tests/api/test_api_v1_polls_id_votes.cpp new file mode 100644 index 0000000..12b3de1 --- /dev/null +++ b/tests/api/test_api_v1_polls_id_votes.cpp @@ -0,0 +1,80 @@ +/* This file is part of mastodon-cpp. + * Copyright © 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include "mastodon-cpp.hpp" +#include "easy/easy.hpp" +#include "easy/entities/poll.hpp" +#include "../environment_variables.hpp" + +using namespace Mastodon; + +SCENARIO ("/api/v1/polls/:id/votes can be called successfully", + "[api][auth][mastodon][pleroma][glitch-soc]") +{ + REQUIRE (access_token != nullptr); + + GIVEN ("instance = " + instance) + { + Mastodon::Easy::API masto(instance, access_token); + return_call ret; + Easy::Poll poll; + bool exception = false; + + WHEN ("POST /api/v1/polls/:id/votes is called") + { + try + { + ret = masto.post(API::v1::polls_id_votes, + { + { "id", { "4823515" } }, + // TODO: Check if this is the right format. + { "choices", { "false", "false", "true", + "false", "false" } } + }); + if (ret.answer == "[]") + { + WARN("Poll not found."); + } + else + { + poll.from_string(ret.answer); + } + } + catch (const std::exception &e) + { + exception = true; + WARN(e.what()); + } + + THEN("No exception is thrown") + AND_THEN ("An error is returned") + AND_THEN ("Answer is invalid") + { + REQUIRE_FALSE(exception); + + REQUIRE(ret.error_code == 12); + REQUIRE(ret.http_error_code != 200); // Pleroma returns 422. + REQUIRE_FALSE(poll.valid()); + REQUIRE(poll.id() == ""); + REQUIRE(poll.error() == "Poll's author can't vote"); + } + } + } +} + From c3e00e2e310a35dbdbeed10eb468d3522ae5b32b Mon Sep 17 00:00:00 2001 From: tastytea Date: Fri, 20 Sep 2019 02:26:07 +0200 Subject: [PATCH 04/11] Added Easy::Conversation. --- README.adoc | 2 +- src/easy/entities/conversation.cpp | 68 +++++++++++++++++++++++ src/easy/entities/conversation.hpp | 77 ++++++++++++++++++++++++++ src/easy/return_types_easy.cpp | 2 + tests/entities/conversation.cpp | 89 ++++++++++++++++++++++++++++++ 5 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 src/easy/entities/conversation.cpp create mode 100644 src/easy/entities/conversation.hpp create mode 100644 tests/entities/conversation.cpp diff --git a/README.adoc b/README.adoc index ebb6cb7..f16834b 100644 --- a/README.adoc +++ b/README.adoc @@ -390,7 +390,7 @@ strings and you can use unsupported fields in an `Entity` by converting it to * [x] Attachment * [x] Card * [x] Context -* [ ] Conversation +* [x] Conversation * [x] Emoji * [x] Filter * [x] Instance diff --git a/src/easy/entities/conversation.cpp b/src/easy/entities/conversation.cpp new file mode 100644 index 0000000..4a81c51 --- /dev/null +++ b/src/easy/entities/conversation.cpp @@ -0,0 +1,68 @@ +/* This file is part of mastodon-cpp. + * Copyright © 2018, 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include "conversation.hpp" +#include "debug.hpp" + +using namespace Mastodon; +using Conversation = Easy::Conversation; + +bool Conversation::valid() const +{ + return Entity::check_valid( + { + "id", + "accounts", + "unread" + }); +} + +const string Conversation::id() const +{ + return get_string("id"); +} + +const std::vector Conversation::accounts() const +{ + const Json::Value node = get("accounts"); + if (node.isArray()) + { + std::vector vec; + std::transform(node.begin(), node.end(), std::back_inserter(vec), + [](const Json::Value &value) + { return Easy::Account(value); }); + return vec; + } + + return {}; +} + +const Easy::Status Conversation::last_status() const +{ + const Json::Value &node = get("last_status"); + if (!node.isNull()) + { + return Easy::Status(node); + } + + return {}; +} + +bool Conversation::unread() const +{ + return get_bool("unread"); +} diff --git a/src/easy/entities/conversation.hpp b/src/easy/entities/conversation.hpp new file mode 100644 index 0000000..19906d5 --- /dev/null +++ b/src/easy/entities/conversation.hpp @@ -0,0 +1,77 @@ +/* This file is part of mastodon-cpp. + * Copyright © 2018, 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef MASTODON_CPP_EASY_CONVERSATION_HPP +#define MASTODON_CPP_EASY_CONVERSATION_HPP + +#include +#include + +#include "../../mastodon-cpp.hpp" +#include "../entity.hpp" +#include "account.hpp" +#include "status.hpp" + +using std::string; + +namespace Mastodon +{ +namespace Easy +{ + /*! + * @brief Class to hold conversations. + * + * @since 0.107.0 + */ + class Conversation : public Entity + { + public: + using Entity::Entity; + + virtual bool valid() const override; + + /*! + * @brief Returns the id of the conversation. + * + * @since 0.107.0 + */ + const string id() const; + + /*! + * @brief Returns the participating accounts. + * + * @since 0.107.0 + */ + const std::vector accounts() const; + + /*! + * @brief Returns the last status. + * + * @since 0.107.0 + */ + const Status last_status() const; + + /*! + * @brief Returns true if unread. + * + * @since 0.107.0 + */ + bool unread() const; + }; +} +} + +#endif // MASTODON_CPP_EASY_CONVERSATION_HPP diff --git a/src/easy/return_types_easy.cpp b/src/easy/return_types_easy.cpp index e9f8af9..c2288af 100644 --- a/src/easy/return_types_easy.cpp +++ b/src/easy/return_types_easy.cpp @@ -34,6 +34,7 @@ #include "easy/entities/pushsubscription.hpp" #include "easy/entities/filter.hpp" #include "easy/entities/poll.hpp" +#include "easy/entities/conversation.hpp" using namespace Mastodon; @@ -94,6 +95,7 @@ template struct Easy::return_entity; template struct Easy::return_entity; template struct Easy::return_entity; template struct Easy::return_entity; +template struct Easy::return_entity; template diff --git a/tests/entities/conversation.cpp b/tests/entities/conversation.cpp new file mode 100644 index 0000000..0ea547b --- /dev/null +++ b/tests/entities/conversation.cpp @@ -0,0 +1,89 @@ +/* This file is part of mastodon-cpp. + * Copyright © 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include "easy/entities/conversation.hpp" +#include "easy/easy.hpp" + +using std::string; +using std::chrono::system_clock; + +using namespace Mastodon; + +SCENARIO ("Easy::Conversation works as intended", "[entity]") +{ + GIVEN ("An Easy::Conversation object") + { + Easy::Conversation conversation; + bool exception = false; + + WHEN ("It is initialized with valid conversation data") + { + const string data = + "\"id\":\"1234567\"," + "\"accounts\":[" + "{\"id\":\"98765\"}," + "{\"id\":\"56789\"}]," + "\"last_status\":null," + "\"unread\":false}"; + + try + { + conversation.from_string(data); + } + catch (const std::exception &e) + { + exception = true; + } + + THEN ("No exception is thrown") + AND_THEN ("Conversation is valid") + AND_THEN ("The attributes are set to the right values") + { + REQUIRE_FALSE(exception); + REQUIRE(conversation.valid()); + REQUIRE(conversation.id() == "1234567"); + REQUIRE(conversation.accounts().size() == 2); + REQUIRE(conversation.unread() == false); + } + } + + WHEN ("It is initialized with an empty string") + { + try + { + conversation.from_string(""); + } + catch (const std::exception &e) + { + exception = true; + } + + THEN ("No exception is thrown") + AND_THEN ("It is not valid") + AND_THEN ("id is empty") + { + REQUIRE_FALSE(exception); + REQUIRE_FALSE(conversation.valid()); + REQUIRE(conversation.id() == ""); + REQUIRE(conversation.accounts().size() == 0); + } + } + } +} From 14a1d92442a1d441a8fce054a290c94b80960c29 Mon Sep 17 00:00:00 2001 From: tastytea Date: Fri, 20 Sep 2019 02:26:47 +0200 Subject: [PATCH 05/11] Added /api/v1/conversations. --- README.adoc | 2 +- src/api/get.cpp | 5 ++ src/mastodon-cpp.hpp | 2 +- tests/api/test_api_v1_conversations.cpp | 74 +++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 tests/api/test_api_v1_conversations.cpp diff --git a/README.adoc b/README.adoc index f16834b..6a87af7 100644 --- a/README.adoc +++ b/README.adoc @@ -370,7 +370,7 @@ strings and you can use unsupported fields in an `Entity` by converting it to ** [x] POST /api/v1/statuses/:id/unpin * Timelines ** [x] GET /api/v1/timelines/home - ** [ ] GET /api/v1/conversations + ** [x] GET /api/v1/conversations ** [x] GET /api/v1/timelines/public ** [x] GET /api/v1/timelines/tag/:hashtag ** [x] GET /api/v1/timelines/list/:list_id diff --git a/src/api/get.cpp b/src/api/get.cpp index 38c74eb..d80a60c 100644 --- a/src/api/get.cpp +++ b/src/api/get.cpp @@ -236,6 +236,11 @@ const return_call API::get(const Mastodon::API::v1 &call, strcall = "/api/v1/polls/" + strid; break; } + case v1::conversations: + { + strcall = "/api/v1/conversations"; + break; + } default: { ttdebug << "ERROR: Invalid argument.\n"; diff --git a/src/mastodon-cpp.hpp b/src/mastodon-cpp.hpp index 0a7bb51..2d1e12f 100644 --- a/src/mastodon-cpp.hpp +++ b/src/mastodon-cpp.hpp @@ -264,7 +264,7 @@ namespace Mastodon statuses_id_unpin, timelines_home, - // timelines_conversations, + conversations, timelines_public, timelines_tag_hashtag, timelines_list_list_id, diff --git a/tests/api/test_api_v1_conversations.cpp b/tests/api/test_api_v1_conversations.cpp new file mode 100644 index 0000000..69a728a --- /dev/null +++ b/tests/api/test_api_v1_conversations.cpp @@ -0,0 +1,74 @@ +/* This file is part of mastodon-cpp. + * Copyright © 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include "mastodon-cpp.hpp" +#include "easy/easy.hpp" +#include "easy/entities/conversation.hpp" +#include "../environment_variables.hpp" + +using namespace Mastodon; + +SCENARIO ("/api/v1/conversations can be called successfully", + "[api][auth][mastodon][glitch-soc]") +{ + REQUIRE (access_token != nullptr); + + GIVEN ("instance = " + instance) + { + Mastodon::Easy::API masto(instance, access_token); + return_call ret; + Easy::Conversation conversation; + bool exception = false; + + WHEN ("GET /api/v1/conversations is called") + { + try + { + ret = masto.get(API::v1::conversations, {{ "limit", { "2" }}}); + if (ret.answer == "[]") + { + WARN("No Conversations found."); + } + else + { + conversation.from_string( + Easy::json_array_to_vector(ret.answer).front()); + } + } + catch (const std::exception &e) + { + exception = true; + WARN(e.what()); + } + + THEN("No exception is thrown") + AND_THEN ("No error is returned") + AND_THEN ("Answer is valid") + { + REQUIRE_FALSE(exception); + + REQUIRE(ret.error_code == 0); + REQUIRE(ret.http_error_code == 200); + REQUIRE(conversation.valid()); + REQUIRE(conversation.id() != ""); + } + } + } +} + From 3446bbf5d662da08ae655a616f0e1c381efb0b20 Mon Sep 17 00:00:00 2001 From: tastytea Date: Fri, 20 Sep 2019 02:29:45 +0200 Subject: [PATCH 06/11] Deleted Easy::Report and GET /api/v1/reports. They are no longer documented by Mastodon. --- README.adoc | 3 -- src/api/get.cpp | 5 --- src/easy/entities/report.cpp | 39 ----------------------- src/easy/entities/report.hpp | 62 ------------------------------------ 4 files changed, 109 deletions(-) delete mode 100644 src/easy/entities/report.cpp delete mode 100644 src/easy/entities/report.hpp diff --git a/README.adoc b/README.adoc index 6a87af7..fc59350 100644 --- a/README.adoc +++ b/README.adoc @@ -346,7 +346,6 @@ strings and you can use unsupported fields in an `Entity` by converting it to ** [x] GET /api/v1/polls/:id ** [x] POST /api/v1/polls/:id/votes * Reports - ** [x] GET /api/v1/reports ^(Deprecated)^ ** [x] POST /api/v1/reports * Scheduled Statuses ** [ ] GET /api/v1/scheduled_statuses @@ -354,7 +353,6 @@ strings and you can use unsupported fields in an `Entity` by converting it to ** [ ] PUT /api/v1/scheduled_statuses/:id ** [ ] DELETE /api/v1/scheduled_statuses/:id * Search - ** [x] GET /api/v1/search ^(Deprecated)^ ** [x] GET /api/v2/search * Statuses ** [x] GET /api/v1/statuses/:id @@ -400,7 +398,6 @@ strings and you can use unsupported fields in an `Entity` by converting it to * [x] Poll * [x] PushSubscription * [x] Relationship -* [ ] Report ^(Deprecated)^ * [x] Results * [x] Status * [ ] ScheduledStatus diff --git a/src/api/get.cpp b/src/api/get.cpp index d80a60c..f3ba41e 100644 --- a/src/api/get.cpp +++ b/src/api/get.cpp @@ -86,11 +86,6 @@ const return_call API::get(const Mastodon::API::v1 &call, strcall = "/api/v1/notifications"; break; } - case v1::reports: - { - strcall = "/api/v1/reports"; - break; - } case v1::timelines_home: { strcall = "/api/v1/timelines/home"; diff --git a/src/easy/entities/report.cpp b/src/easy/entities/report.cpp deleted file mode 100644 index 6b134c2..0000000 --- a/src/easy/entities/report.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* This file is part of mastodon-cpp. - * Copyright © 2018, 2019 tastytea - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include "report.hpp" - -using namespace Mastodon; -using Report = Easy::Report; - -bool Report::valid() const -{ - return Entity::check_valid( - { - "id", - "action_taken" - }); -} - -bool Report::action_taken() const -{ - return get_bool("action_taken"); -} - -const string Report::id() const -{ - return get_string("id"); -} diff --git a/src/easy/entities/report.hpp b/src/easy/entities/report.hpp deleted file mode 100644 index d91a466..0000000 --- a/src/easy/entities/report.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* This file is part of mastodon-cpp. - * Copyright © 2018, 2019 tastytea - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#ifndef MASTODON_CPP_EASY_REPORT_HPP -#define MASTODON_CPP_EASY_REPORT_HPP - -#include -#include - -#include "../../mastodon-cpp.hpp" -#include "../entity.hpp" - -using std::string; - -namespace Mastodon -{ -namespace Easy -{ - /*! - * @brief Class to hold reports - * - * before 0.11.0 - */ - class Report : public Entity - { - public: - using Entity::Entity; - - virtual bool valid() const override; - - /*! - * @brief Returns true if an action was taken in response to the - * report - * - * @since before 0.11.0 - */ - bool action_taken() const; - - /*! - * @brief Returns the ID of the report - * - * @since before 0.11.0 - */ - const string id() const; - }; -} -} - -#endif // MASTODON_CPP_EASY_REPORT_HPP From 7f80bff4e1d937c2bc30e0b3e514a9e83185d326 Mon Sep 17 00:00:00 2001 From: tastytea Date: Fri, 20 Sep 2019 02:33:42 +0200 Subject: [PATCH 07/11] Add support for /api/v1/streaming/health. --- README.adoc | 1 + src/api/get.cpp | 5 +++++ src/mastodon-cpp.hpp | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index fc59350..6c7ceed 100644 --- a/README.adoc +++ b/README.adoc @@ -373,6 +373,7 @@ strings and you can use unsupported fields in an `Entity` by converting it to ** [x] GET /api/v1/timelines/tag/:hashtag ** [x] GET /api/v1/timelines/list/:list_id * Streaming API + ** [x] GET /api/v1/streaming/health ** [x] GET /api/v1/streaming/user ** [x] GET /api/v1/streaming/public ** [x] GET /api/v1/streaming/public/local diff --git a/src/api/get.cpp b/src/api/get.cpp index f3ba41e..2b6defa 100644 --- a/src/api/get.cpp +++ b/src/api/get.cpp @@ -236,6 +236,11 @@ const return_call API::get(const Mastodon::API::v1 &call, strcall = "/api/v1/conversations"; break; } + case v1::streaming_health: + { + strcall = "/api/v1/streaming/health"; + break; + } default: { ttdebug << "ERROR: Invalid argument.\n"; diff --git a/src/mastodon-cpp.hpp b/src/mastodon-cpp.hpp index 2d1e12f..048e9d9 100644 --- a/src/mastodon-cpp.hpp +++ b/src/mastodon-cpp.hpp @@ -269,7 +269,7 @@ namespace Mastodon timelines_tag_hashtag, timelines_list_list_id, - // streaming_health, + streaming_health, streaming_user, streaming_public, streaming_public_local, From ff649fd2ebe3703f015efb8da890661d8fdfa639 Mon Sep 17 00:00:00 2001 From: tastytea Date: Fri, 20 Sep 2019 02:37:33 +0200 Subject: [PATCH 08/11] Add support for /api/v1/streaming/hashtag/local. --- README.adoc | 2 +- src/api/get_stream.cpp | 5 +++++ src/mastodon-cpp.hpp | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 6c7ceed..81a43d3 100644 --- a/README.adoc +++ b/README.adoc @@ -378,7 +378,7 @@ strings and you can use unsupported fields in an `Entity` by converting it to ** [x] GET /api/v1/streaming/public ** [x] GET /api/v1/streaming/public/local ** [x] GET /api/v1/streaming/hashtag - ** [ ] GET /api/v1/streaming/hashtag/local + ** [x] GET /api/v1/streaming/hashtag/local ** [x] GET /api/v1/streaming/list ** [ ] GET /api/v1/streaming/direct diff --git a/src/api/get_stream.cpp b/src/api/get_stream.cpp index 29e6b3e..b57752e 100644 --- a/src/api/get_stream.cpp +++ b/src/api/get_stream.cpp @@ -51,6 +51,11 @@ void API::get_stream(const Mastodon::API::v1 &call, strcall = "/api/v1/streaming/hashtag"; break; } + case v1::streaming_hashtag_local: + { + strcall = "/api/v1/streaming/hashtag/local"; + break; + } case v1::streaming_list: { strcall = "/api/v1/streaming/list"; diff --git a/src/mastodon-cpp.hpp b/src/mastodon-cpp.hpp index 048e9d9..cd76fa5 100644 --- a/src/mastodon-cpp.hpp +++ b/src/mastodon-cpp.hpp @@ -274,7 +274,7 @@ namespace Mastodon streaming_public, streaming_public_local, streaming_hashtag, - // streaming_hashtag_local, + streaming_hashtag_local, streaming_list, // streaming_direct, From d100d1a2b6a6378f003d67f23bcd2d81ac2ec65c Mon Sep 17 00:00:00 2001 From: tastytea Date: Fri, 20 Sep 2019 02:38:56 +0200 Subject: [PATCH 09/11] Add support for GET /api/v1/streaming/direct. --- README.adoc | 2 +- src/api/get_stream.cpp | 5 +++++ src/mastodon-cpp.hpp | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 81a43d3..4bc1b69 100644 --- a/README.adoc +++ b/README.adoc @@ -380,7 +380,7 @@ strings and you can use unsupported fields in an `Entity` by converting it to ** [x] GET /api/v1/streaming/hashtag ** [x] GET /api/v1/streaming/hashtag/local ** [x] GET /api/v1/streaming/list - ** [ ] GET /api/v1/streaming/direct + ** [x] GET /api/v1/streaming/direct ==== Entities diff --git a/src/api/get_stream.cpp b/src/api/get_stream.cpp index b57752e..69bd7ea 100644 --- a/src/api/get_stream.cpp +++ b/src/api/get_stream.cpp @@ -61,6 +61,11 @@ void API::get_stream(const Mastodon::API::v1 &call, strcall = "/api/v1/streaming/list"; break; } + case v1::streaming_direct: + { + strcall = "/api/v1/streaming/direct"; + break; + } default: { const uint8_t err = static_cast(error::INVALID_ARGUMENT); diff --git a/src/mastodon-cpp.hpp b/src/mastodon-cpp.hpp index cd76fa5..98c0b37 100644 --- a/src/mastodon-cpp.hpp +++ b/src/mastodon-cpp.hpp @@ -276,7 +276,7 @@ namespace Mastodon streaming_hashtag, streaming_hashtag_local, streaming_list, - // streaming_direct, + streaming_direct, // Glitch-Soc bookmarks, From f8ed45dcc401cccb322def38b0c713c64b2b51f7 Mon Sep 17 00:00:00 2001 From: tastytea Date: Fri, 20 Sep 2019 02:41:27 +0200 Subject: [PATCH 10/11] Deleted report from return types and added Poll and Conversations. --- src/easy/all.hpp | 3 ++- src/easy/return_types_easy.cpp | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/easy/all.hpp b/src/easy/all.hpp index 47e931d..12e7a29 100644 --- a/src/easy/all.hpp +++ b/src/easy/all.hpp @@ -29,12 +29,13 @@ #include "entities/mention.hpp" #include "entities/notification.hpp" #include "entities/relationship.hpp" -#include "entities/report.hpp" #include "entities/results.hpp" #include "entities/status.hpp" #include "entities/tag.hpp" #include "entities/token.hpp" #include "entities/pushsubscription.hpp" #include "entities/filter.hpp" +#include "entities/poll.hpp" +#include "entities/conversation.hpp" #endif // MASTODON_CPP_EASY_ALL_HPP diff --git a/src/easy/return_types_easy.cpp b/src/easy/return_types_easy.cpp index c2288af..6da8a6a 100644 --- a/src/easy/return_types_easy.cpp +++ b/src/easy/return_types_easy.cpp @@ -26,7 +26,6 @@ #include "easy/entities/mention.hpp" #include "easy/entities/notification.hpp" #include "easy/entities/relationship.hpp" -#include "easy/entities/report.hpp" #include "easy/entities/results.hpp" #include "easy/entities/status.hpp" #include "easy/entities/tag.hpp" @@ -87,7 +86,6 @@ template struct Easy::return_entity; template struct Easy::return_entity; template struct Easy::return_entity; template struct Easy::return_entity; -template struct Easy::return_entity; template struct Easy::return_entity; template struct Easy::return_entity; template struct Easy::return_entity; @@ -134,10 +132,11 @@ template struct Easy::return_entity_vector; template struct Easy::return_entity_vector; template struct Easy::return_entity_vector; template struct Easy::return_entity_vector; -template struct Easy::return_entity_vector; template struct Easy::return_entity_vector; template struct Easy::return_entity_vector; template struct Easy::return_entity_vector; template struct Easy::return_entity_vector; template struct Easy::return_entity_vector; template struct Easy::return_entity_vector; +template struct Easy::return_entity_vector; +template struct Easy::return_entity_vector; From 14d2e53cfcc4fd36a8aff5e952674f7e48c769c5 Mon Sep 17 00:00:00 2001 From: tastytea Date: Fri, 20 Sep 2019 02:52:56 +0200 Subject: [PATCH 11/11] =?UTF-8?q?Add=20support=20for=20the=20streaming=20e?= =?UTF-8?q?vent=20=E2=80=9Cfilters=5Fchanged=E2=80=9D.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/easy/easy.cpp | 13 ++++++++----- src/easy/types_easy.hpp | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/easy/easy.cpp b/src/easy/easy.cpp index 0f26690..f583e77 100644 --- a/src/easy/easy.cpp +++ b/src/easy/easy.cpp @@ -53,7 +53,8 @@ const vector Easy::parse_stream( const std::string &streamdata) { string stream = streamdata; - std::regex reevent("event: (update|notification|delete|ERROR)\ndata: (.*)\n"); + std::regex reevent("event: (update|notification|delete|filters_changed" + "|ERROR)\ndata: (.*)\n"); std::smatch match; std::vector vec = {}; @@ -63,14 +64,16 @@ const vector Easy::parse_stream( const string &data = match[2].str(); event_type type = event_type::Undefined; - if (event.compare("update") == 0) + if (event == "update") type = event_type::Update; - else if (event.compare("notification") == 0) + else if (event == "notification") type = event_type::Notification; - else if (event.compare("delete") == 0) + else if (event == "delete") type = event_type::Delete; - else if (event.compare("ERROR") == 0) + else if (event == "ERROR") type = event_type::Error; + else if (event == "filters_changed") + type = event_type::Filters_changed; vec.push_back({ type, data }); stream = match.suffix().str(); diff --git a/src/easy/types_easy.hpp b/src/easy/types_easy.hpp index 1591e5d..cb2c5cc 100644 --- a/src/easy/types_easy.hpp +++ b/src/easy/types_easy.hpp @@ -41,6 +41,7 @@ namespace Easy Notification, Delete, Error, + Filters_changed, Undefined };