diff --git a/.gitignore b/.gitignore index 84c048a..cace064 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /build/ +/doc/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 285cb5c..aee1539 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required (VERSION 3.7) project (mastodon-cpp - VERSION 0.0.2 + VERSION 0.0.3 LANGUAGES CXX ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..e4886c8 --- /dev/null +++ b/Doxyfile @@ -0,0 +1,198 @@ +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "mastodon-cpp" +PROJECT_NUMBER = 0.0.0 +INPUT = README.md src/mastodon-cpp.hpp +USE_MDFILE_AS_MAINPAGE = README.md +CREATE_SUBDIRS = NO +ALLOW_UNICODE_NAMES = YES +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 4 +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +MARKDOWN_SUPPORT = YES +AUTOLINK_SUPPORT = YES +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +GROUP_NESTED_COMPOUNDS = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO +TYPEDEF_HIDES_STRUCT = NO +LOOKUP_CACHE_SIZE = 0 +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_PACKAGE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +HIDE_COMPOUND_REFERENCE= NO +SHOW_INCLUDE_FILES = YES +SHOW_GROUPED_MEMB_INC = NO +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +INPUT_ENCODING = UTF-8 +RECURSIVE = NO +EXCLUDE_SYMLINKS = NO +EXAMPLE_PATH = examples +EXAMPLE_RECURSIVE = NO +FILTER_SOURCE_FILES = NO +SOURCE_BROWSER = NO +INLINE_SOURCES = YES +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +SOURCE_TOOLTIPS = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +CLANG_ASSISTED_PARSING = NO +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +GENERATE_HTML = YES +HTML_OUTPUT = doc/html +HTML_FILE_EXTENSION = .html +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = NO +HTML_DYNAMIC_SECTIONS = NO +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +GENERATE_TREEVIEW = NO +ENUM_VALUES_PER_LINE = 4 +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +USE_MATHJAX = NO +MATHJAX_FORMAT = HTML-CSS +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +EXTERNAL_SEARCH = NO +SEARCHDATA_FILE = searchdata.xml +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +LATEX_BIB_STYLE = plain +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_SOURCE_CODE = NO +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_SUBDIR = +MAN_LINKS = NO +GENERATE_XML = NO +XML_OUTPUT = xml +XML_PROGRAMLISTING = YES +GENERATE_DOCBOOK = NO +DOCBOOK_OUTPUT = docbook +DOCBOOK_PROGRAMLISTING = NO +GENERATE_AUTOGEN_DEF = NO +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +SKIP_FUNCTION_MACROS = YES +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +EXTERNAL_PAGES = YES +PERL_PATH = /usr/bin/perl +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +UML_LIMIT_NUM_FIELDS = 10 +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +INTERACTIVE_SVG = NO +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/README.md b/README.md index 1df331c..8117e2d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -**mastodon-cpp** is a CPP wrapper for the Mastodon API. The aim is to be as simple as possible. +**mastodon-cpp** is a C++ 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. +All versions below 1.0.0 (SOVERSION 0) are considered insecure, unstable and can change any time. # Install ## Dependencies @@ -8,6 +8,7 @@ All versions below 1.0.0 (SOVERSION 0) are considered insecure, unstable and can * C++ compiler (tested: gcc 6.4) * [cmake](https://cmake.org/) (tested: 3.9.6) * [boost](http://www.boost.org/) (tested: 1.63.0) + * Optional: [doxygen](https://www.stack.nl/~dimitri/doxygen/) (tested: 1.8.13) ## Get sourcecode ### Development version @@ -20,15 +21,12 @@ All versions below 1.0.0 (SOVERSION 0) are considered insecure, unstable and can make # Usage - Mastodon::API masto("social.example.com", "access token"); - std::cout << masto.get(Mastodon::API::v1::timelines_home) << '\n'; - std::cout << masto.get(Mastodon::API::v1::accounts_id, "12345") << '\n'; -There is an example in `src/example`. +The reference can be generated with `build_doc.sh`, if doxygen is installed. Or just look in `src/mastodon-cpp.hpp`. There is an example in `src/example`. # TODO * Version 0.1.0 - * [ ] Implement all GET methods + * [x] Implement all GET methods * [ ] Proper error handling * [x] Network stuff * [ ] Comprehensive example @@ -37,8 +35,8 @@ There is an example in `src/example`. * [ ] Implement all POST methods * [ ] Implement all DELETE methods * Later - [ ] Escape user input - [ ] Asynchronous I/O + * [ ] Escape user input + * [ ] Asynchronous I/O ## Status of implementation * [x] GET /api/v1/accounts/:id @@ -108,6 +106,7 @@ There is an example in `src/example`. [Full reference](https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md) # Copyright + Copyright © 2018 tastytea . License GPLv3: GNU GPL version 3 . This program comes with ABSOLUTELY NO WARRANTY. This is free software, diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..2db2bdb --- /dev/null +++ b/build.sh @@ -0,0 +1,9 @@ +#!/bin/sh +mkdir -p build && \ +cd build/ && +cmake .. && \ +make + +if [ "$(basename ${PWD})" == "build" ]; then + cd .. +fi diff --git a/build_doc.sh b/build_doc.sh new file mode 100755 index 0000000..580bd7c --- /dev/null +++ b/build_doc.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +if [ -f Doxyfile ]; then + mkdir -p doc + (cat Doxyfile && echo -n "PROJECT_NUMBER = " && + grep -Eo '[0-9]+.[0-9]+.[0-9]+$' CMakeLists.txt) \ + | doxygen - +fi diff --git a/src/api_get.cpp b/src/api_get.cpp index 9ccab05..343f24d 100644 --- a/src/api_get.cpp +++ b/src/api_get.cpp @@ -95,6 +95,8 @@ const string API::get(const Mastodon::API::v1 &call, const std::vector ¶meters) { string strcall = ""; + char delim = '?'; + switch (call) { case v1::accounts_id: @@ -111,9 +113,11 @@ const string API::get(const Mastodon::API::v1 &call, break; case v1::accounts_relationships: strcall = "/api/v1/accounts/relationships?id=" + argument; + delim = '&'; break; case v1::accounts_search: strcall = "/api/v1/accounts/search?q=" + argument; + delim = '&'; break; case v1::accounts_id_lists: strcall = "/api/v1/accounts/" + argument + "/lists"; @@ -129,6 +133,7 @@ const string API::get(const Mastodon::API::v1 &call, break; case v1::search: strcall = "/api/v1/search?q=" + argument; + delim = '&'; break; case v1::statuses_id: strcall = "/api/v1/statuses/" + argument; @@ -157,6 +162,18 @@ const string API::get(const Mastodon::API::v1 &call, break; } + if (parameters.size() > 0) + { + for (const string p : parameters) + { + strcall += delim + p; + if (delim == '?') + { + delim = '&'; + } + } + } + string answer; _http.request_sync(http::method::GET, strcall, answer); return answer; diff --git a/src/example/example.cpp b/src/example/example.cpp index 4d35c1d..385846c 100644 --- a/src/example/example.cpp +++ b/src/example/example.cpp @@ -2,6 +2,8 @@ */ #include +#include +#include #include "../mastodon-cpp.hpp" using Mastodon::API; @@ -16,5 +18,12 @@ int main(int argc, char *argv[]) Mastodon::API masto(argv[1], argv[2]); - std::cout << masto.get(API::v1::timelines_tag_hashtag, "FOSS") << '\n'; + std::vector parameters = + { + "limit=2", + "only_media=1" + }; + std::cout << + masto.get(API::v1::accounts_id_statuses, "44897", parameters) << + '\n'; } diff --git a/src/mastodon-cpp.hpp b/src/mastodon-cpp.hpp index 4c98a1b..a91cb6b 100644 --- a/src/mastodon-cpp.hpp +++ b/src/mastodon-cpp.hpp @@ -25,97 +25,177 @@ namespace Mastodon { - class API +class API +{ +public: + /*! + * @brief A list of all API calls. + * + * The original `/` are substituted by `_`. Currently only GET + * requests. + */ + enum class v1 + { + accounts_id, + accounts_verify_credentials, + accounts_id_followers, + accounts_id_following, + accounts_id_statuses, + accounts_relationships, + accounts_search, + blocks, + domain_blocks, + favourites, + follow_requests, + instance, + custom_emojis, + lists, + accounts_id_lists, + lists_id_accounts, + lists_id, + mutes, + notifications, + notifications_id, + reports, + search, + statuses_id, + statuses_id_context, + statuses_id_card, + statuses_id_reblogged_by, + statuses_id_favourited_by, + timelines_home, + timelines_public, + timelines_tag_hashtag, + timelines_list_list_id + }; + + /*! + * @brief Constructs a new API object. + * + * @param instance The hostname of your instance + * @param access_token Your access token. You have to generate it + * manually for now. + */ + explicit API(const std::string &instance, + const std::string &access_token); + + /*! + * @brief Make a GET request which doesn't require an argument. + * + * @param call A call defined in Mastodon::API::v1 + * + * @return The answer from the server. Usually JSON. + */ + const std::string get(const Mastodon::API::v1 &call); + + /*! + * @brief Make a GET request which requires an argument + * + * @param call A call defined in Mastodon::API::v1 + * @param argument The non-optional argument + * + * @return The answer from the server. Usually JSON. + */ + const std::string get(const Mastodon::API::v1 &call, + const std::string &argument); + + /*! + * @brief Make a GET request which doesn't require an argument, pass + * optional parameters. + * + * @param call A call defined in Mastodon::API::v1 + * @param parameters A std::vector containing optional parameters in the + * form `field=value` + * + * @return The answer from the server. Usually JSON. + */ + const std::string get(const Mastodon::API::v1 &call, + const std::vector ¶meters); + + /*! + * @brief Make a GET request which requires an argument, pass optional + * parameters. + * + * Example: + * + * Mastodon::API masto(argv[1], argv[2]); + * std::vector parameters = + * { + * "limit=2", + * "only_media=1" + * }; + * masto.get(Mastodon::API::v1::accounts_id_statuses, "12345", parameters); + * + * @param call A call defined in Mastodon::API::v1 + * @param argument The non-optional argument + * @param parameters A std::vector containing optional parameters in the + * form `field=value` + * + * @return The answer from the server. Usually JSON. + */ + const std::string get(const Mastodon::API::v1 &call, + const std::string &argument, + const std::vector ¶meters); + + /*! + * @brief Make a custom GET request. + * + * @param call String in the form `/api/v1/example` + * + * @return The answer from the server. Usually JSON. + */ + const std::string get(const std::string &call); + + /*! + * @brief Sets the useragent. Default is mastodon-cpp/version. + * + * @param useragent The useragent + */ + const void set_useragent(const std::string &useragent); + + /*! + * @brief Gets the useragent. + * + * @return The useragent. + */ + const std::string get_useragent() const; + +private: + const std::string _instance; + const std::string _access_token; + std::string _useragent; + + class http { public: - enum class v1 + enum class method { - accounts_id, - accounts_verify_credentials, - accounts_id_followers, - accounts_id_following, - accounts_id_statuses, - accounts_relationships, - accounts_search, - blocks, - domain_blocks, - favourites, - follow_requests, - instance, - custom_emojis, - lists, - accounts_id_lists, - lists_id_accounts, - lists_id, - mutes, - notifications, - notifications_id, - reports, - search, - statuses_id, - statuses_id_context, - statuses_id_card, - statuses_id_reblogged_by, - statuses_id_favourited_by, - timelines_home, - timelines_public, - timelines_tag_hashtag, - timelines_list_list_id + GET, + PATCH, + POST, + DELETE }; - 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 &call); - const std::string get(const Mastodon::API::v1 &call, - const std::vector ¶meters); - const std::string get(const Mastodon::API::v1 &call, - const std::string &argument, - const std::vector ¶meters); - const std::string get(const Mastodon::API::v1 &call, - const std::string &argument); - // Supply a custom call as string. - const std::string get(const std::string &call); - - const void set_useragent(const std::string &useragent); - const std::string get_useragent() const; + explicit http(const API &api, const std::string &instance, + const std::string &access_token); + 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 API &parent; 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 API &api, const std::string &instance, - const std::string &access_token); - 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 API &parent; - const std::string _instance; - const std::string _access_token; - boost::asio::ssl::context _ctx; - boost::asio::io_service _io_service; - boost::asio::ip::tcp::resolver _resolver; - boost::asio::ssl::stream _socket; - } _http; - }; + boost::asio::ssl::context _ctx; + boost::asio::io_service _io_service; + boost::asio::ip::tcp::resolver _resolver; + boost::asio::ssl::stream _socket; + } _http; +}; } #endif