= mastodon-cpp
:toc: preamble

*mastodon-cpp* is a C++ wrapper for the Mastodon API. You submit an API call
and get the raw JSON or easy to use abstractions.

== Usage

The HTML reference can be generated with `build_doc.sh`, if doxygen is
installed. It is also available at
https://doc.schlomp.space/mastodon-cpp/annotated.html[doc.schlomp.space/mastodon-cpp/].
There are more
https://schlomp.space/tastytea/mastodon-cpp/src/branch/master/examples[examples]
in `examples/`.

=== Examples

.Print own account as JSON to stdout.
====
[source,c++]
----
#include <iostream>
#include <mastodon-cpp/mastodon-cpp.hpp>

int main()
{
    Mastodon::API masto("social.example.com", "auth_token");
    std::cout << masto.get(Mastodon::API::v1::accounts_verify_credentials);
    std::cout << std::endl;
}
----
====

.Use the `Easy` interface to get the last posts from the federated timeline.
====
[source,c++]
----
#include <iostream>
#include <string>
#include <mastodon-cpp/mastodon-cpp.hpp>
#include <mastodon-cpp/easy/all.hpp>

using Mastodon;

int main()
{
    Easy::API masto("social.example", "");
    return_call ret = masto.get(API::v1::timelines_public);

    for (const std::string &str : Easy::json_array_to_vector(ret.answer))
    {
        Easy::Status status(str);
        std::cout << "  " << status.account().acct() << " wrote:\n";
        std::cout << status.content() << '\n';
    }
}
----
====

=== Compiling your project

A project consisting of one file can be compiled as follows:

[source,shell]
----
g++ --std=c++14 -lmastodon-cpp example.cpp
----

=== List of types

Learn more at <https://doc.schlomp.space/mastodon-cpp/namespaceMastodon.html>
and <https://doc.schlomp.space/mastodon-cpp/namespaceMastodon_1_1Easy.html>.

Not included in this list are entities.

==== Return types

* `Mastodon::return_call`: Contains the response from `Mastodon::API` calls.
* `Mastodon::Easy::return_entity`: Contains the response from high-level
  functions that return a single `Mastodon::Easy::Entity`.
* `Mastodon::Easy::return_entities_vector`: Contains the response from
  high-level functions that return multiple `Mastodon::Easy::Entity`.

==== Other types

* `Mastodon::parameters`: Vector of `Mastodon::param` with custom `find()`, for
  specifying parameters to an `Mastodon::API` call.
* `Mastodon::http_method`: HTTP method of an `Mastodon::API` call.
* `Mastodon::Easy::event_type`: Event types returned in streams.
* `Mastodon::Easy::visibility_type`: Describes the visibility of a post.
* `Mastodon::Easy::attachment_type`: Describes the type of attachment.
* `Mastodon::Easy::card_type`: Describes the type of card.
* `Mastodon::Easy::notification_type`: The type of the notification.
* `Mastodon::Easy::context_type`: Describes the context of a filter.
* `Mastodon::Easy::stream_event_type`: Type and data of an events returned in
  streams.
* `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.

=== Error codes

[options="header",cols=">,<"]
|===================================================
| Code | Explanation
|    0 | No error
|   22 | Invalid argument
|   78 | URL changed (HTTP 301 or 308)
|  110 | Connection timed out
|  111 | Connection refused (check http_error_code)
|  113 | No route to host / Could not resolve host
|  192 | curlpp runtime error
|  193 | curlpp logic error
|  255 | Unknown error
|===================================================

If you use a debug build, you get more verbose error messages.

=== Useful links

* https://docs.joinmastodon.org/[Mastodon documentation]
* https://git.pleroma.social/pleroma/pleroma/tree/develop/docs/api[Pleroma documentation]
* https://glitch-soc.github.io/docs/#whats-different[glitch-soc documentation]

== Install

=== Upgrading from versions below 0.100.0

Starting with version `0.100.0`, large parts of the library have been rewritten.
Upgrading from previous versions will require extensive code changes. You can
keep using the old version, it is archived in the branch
https://schlomp.space/tastytea/mastodon-cpp/src/branch/pre-0.100.0[pre-0.100.0].
It will receive bug-fixes for a while but no new features.

=== Packages

Every https://schlomp.space/tastytea/mastodon-cpp/releases[release] includes
packages for Debian and Centos. Gentoo packages are available in my overlay.

==== Gentoo

Add my https://schlomp.space/tastytea/overlay[repository] and
install it from there.

[source,shell]
----
eselect repository enable tastytea
echo 'dev-cpp/mastodon-cpp ~amd64' >> /etc/portage/package.accept_keywords/mastodon-cpp
emaint sync -r tastytea
emerge -a dev-cpp/mastodon-cpp
----

==== DEB and RPM

Prebuilt DEB and RPM packages for x86_64(amd64) are provided with each release.
`.deb` packages are built on Debian stretch and `.rpm` packages are built on
CentOS 7. These packages are automatically built and not tested.

To use the `.deb` package on Debian stretch, you will need
https://packages.debian.org/libcurlpp0[libcurlpp0] from sid.

To use the `.rpm` package on CentOS 7, you will need
https://download.fedoraproject.org/pub/epel/6/x86_64/Packages/c/[curlpp]
from EPEL 6.

=== From source

==== Dependencies

* Tested OS: Linux
* C++ compiler (tested: https://gcc.gnu.org/[gcc] 6/8/9,
  https://llvm.org/[clang] 5/6)
* https://cmake.org/[cmake] (at least: 3.6)
* https://pkgconfig.freedesktop.org/wiki/[pkgconfig] (tested: 0.29 / 0.27)
* http://www.curlpp.org/[curlpp] (tested: 0.8)
* Optional
  ** Easy interface & Examples:
     https://github.com/open-source-parsers/jsoncpp[jsoncpp] (tested: 1.8 / 1.7)
  ** Documentation: https://www.stack.nl/~dimitri/doxygen/[doxygen] (tested: 1.8)
  ** DEB package: https://packages.qa.debian.org/dpkg[dpkg] (tested: 1.18)
  ** RPM package: http://www.rpm.org[rpm-build] (tested: 4.11)
  ** Tests: https://github.com/catchorg/Catch2[catch] (tested: 2.5 / 1.2)

.Install dependencies in Debian stretch.
====
[source,shell]
----
echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
apt-get update
apt-get install build-essential cmake pkg-config libcurl4-openssl-dev libjsoncpp-dev doxygen file
apt-get install -t sid libcurlpp-dev
----
====

==== Get sourcecode

===== Release

Download the current release at
https://schlomp.space/tastytea/mastodon-cpp/releases[schlomp.space].

===== Development version

[source,shell]
----
git clone https://schlomp.space/tastytea/mastodon-cpp.git
----

==== Compile

[source,shell]
----
mkdir build
cd build/
cmake ..
cmake --build . -- -j$(nproc --ignore=1)
----

.cmake options:
* `-DCMAKE_BUILD_TYPE=Debug` for a debug build.
* `-DWITH_EASY=NO` to not build the Easy abstractions and to get rid of the
  jsoncpp-dependency (not recommended).
* `-DWITH_EXAMPLES=YES` if you want to compile the examples.
* `-DWITH_TESTS=YES` if you want to compile the tests.
* `-DEXTRA_TEST_ARGS` to run only some tests
  (https://github.com/catchorg/Catch2/blob/master/docs/command-line.md#specifying-which-tests-to-run[format]).
  ** Possible tags: `[api]`, `[auth]`, `[mastodon]`, `[glitch-soc]`,
     `[pleroma]`, `[upload]`, `[entity]`.
* `-DWITH_DOC=NO` if you don't want to compile the HTML reference.
* One of:
  ** `-DWITH_DEB=YES` if you want to be able to generate a deb-package.
  ** `-DWITH_RPM=YES` if you want to be able to generate an rpm-package.

.Run only tests for glitch-soc features that don't upload any files.
====
[source,shell]
----
cmake -DWITH_TESTS=YES -DEXTRA_TEST_ARGS=[glitch-soc]~[upload] ..
----
====

==== Tests

You can run the tests with `ctest` inside the build directory. You need to set
the environment variable `MASTODON_CPP_ACCESS_TOKEN` to an access token with the
scopes _read_, _write_ and _follow_ for tests tagged with `[auth]`.
You can select the instance to use with `MASTODON_CPP_INSTANCE`, the default is
_likeable.space_. You can select the user ID with `MASTODON_CPP_USER_ID`, the
default is _9hnrrVPriLiLVAhfVo_. You can select the status ID with
`MASTODON_CPP_STATUS_ID`, the default is _9hwnuJMq3eTdO4s1PU_. You can select
the filter ID with `MASTODON_CPP_FILTER_ID`. You can select the list ID with
`MASTODON_CPP_LIST_ID`, the default is _2_. You can select the media ID with
`MASTODON_CPP_MEDIA_ID`, the default is _2127742613_.

.Requirements for the test-user:
* Have at least 1 follower.
* Follow at least 1 account.
* Have at least 1 account endorsed.
* Have at least 1 public or unlisted status.
* Have at least 1 post favourited.
* Have no follow requests.
* Have at least 1 list with at least one account in it.
* have at least 1 account muted.

== Status of implementation

You can still use unsupported calls by using `API::get` and the others with
strings and you can use unsupported fields in an `Entity` by converting it to
`Json::Value`.

=== Mastodon API

==== Calls

* Accounts
  ** [x] GET /api/v1/accounts/:id
  ** [x] POST /api/v1/accounts
  ** [x] GET /api/v1/accounts/verify_credentials
  ** [x] PATCH /api/v1/accounts/update_credentials
  ** [x] GET /api/v1/accounts/:id/followers
  ** [x] GET /api/v1/accounts/:id/following
  ** [x] GET /api/v1/accounts/:id/statuses
  ** [x] POST /api/v1/accounts/:id/follow
  ** [x] POST /api/v1/accounts/:id/unfollow
  ** [x] GET /api/v1/accounts/relationships
  ** [x] GET /api/v1/accounts/search
* Apps
  ** [x] POST /api/v1/apps
  ** [x] GET /api/v1/apps/verify_credentials
* Blocks
  ** [x] GET /api/v1/blocks
  ** [x] POST /api/v1/accounts/:id/block
  ** [x] POST /api/v1/accounts/:id/unblock
* Custom emoji
  ** [x] GET /api/v1/custom_emojis
* Domain blocks
  ** [x] GET /api/v1/domain_blocks
  ** [x] POST /api/v1/domain_blocks
  ** [x] DELETE /api/v1/domain_blocks
* Endorsements
  ** [x] GET /api/v1/endorsements
  ** [x] POST /api/v1/accounts/:id/pin
  ** [x] POST /api/v1/accounts/:id/unpin
* Favourites
  ** [x] GET /api/v1/favourites
  ** [x] POST /api/v1/statuses/:id/favourite
  ** [x] POST /api/v1/statuses/:id/unfavourite
* Filters
  ** [x] GET /api/v1/filters
  ** [x] POST /api/v1/filters
  ** [x] GET /api/v1/filters/:id
  ** [x] PUT /api/v1/filters/:id
  ** [x] DELETE /api/v1/filters/:id
* Follow requests
  ** [x] GET /api/v1/follow_requests
  ** [x] POST /api/v1/follow_requests/:id/authorize
  ** [x] POST /api/v1/follow_requests/:id/reject
* Follow suggestions
  ** [x] GET /api/v1/suggestions
  ** [x] DELETE /api/v1/suggestions/:account_id
* Instances
  ** [x] GET /api/v1/instance
* Lists
  ** [x] GET /api/v1/lists
  ** [x] GET /api/v1/accounts/:id/lists
  ** [x] GET /api/v1/lists/:id/accounts
  ** [x] GET /api/v1/lists/:id
  ** [x] POST /api/v1/lists
  ** [x] PUT /api/v1/lists/:id
  ** [x] DELETE /api/v1/lists/:id
  ** [x] POST /api/v1/lists/:id/accounts
  ** [x] DELETE /api/v1/lists/:id/accounts
* Media attachments
  ** [x] POST /api/v1/media
  ** [x] PUT /api/v1/media/:id
* Mutes
  ** [x] GET /api/v1/mutes
  ** [x] POST /api/v1/accounts/:id/mute
  ** [x] POST /api/v1/accounts/:id/unmute
  ** [x] POST /api/v1/statuses/:id/mute
  ** [x] POST /api/v1/statuses/:id/unmute
* Notifications
  ** [x] GET /api/v1/notifications
  ** [x] GET /api/v1/notifications/:id
  ** [x] POST /api/v1/notifications/clear
  ** [x] POST /api/v1/notifications/dismiss
  ** [x] POST /api/v1/push/subscription
  ** [x] GET /api/v1/push/subscription
  ** [x] PUT /api/v1/push/subscription
  ** [x] DELETE /api/v1/push/subscription
* Polls
  ** [ ] GET /api/v1/polls/:id
  ** [ ] 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
  ** [ ] GET /api/v1/scheduled_statuses/:id
  ** [ ] 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
  ** [x] GET /api/v1/statuses/:id/context
  ** [x] GET /api/v1/statuses/:id/card
  ** [x] GET /api/v1/statuses/:id/reblogged_by
  ** [x] GET /api/v1/statuses/:id/favourited_by
  ** [x] POST /api/v1/statuses
  ** [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/pin
  ** [x] POST /api/v1/statuses/:id/unpin
* Timelines
  ** [x] GET /api/v1/timelines/home
  ** [ ] 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
* Streaming API
  ** [x] GET /api/v1/streaming/user
  ** [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/list
  ** [ ] GET /api/v1/streaming/direct

==== Entities

* [x] Account
* [x] Application
* [x] Attachment
* [x] Card
* [x] Context
* [ ] Conversation
* [x] Emoji
* [x] Filter
* [x] Instance
* [x] List
* [x] Mention
* [x] Notification
* [ ] Poll
* [x] PushSubscription
* [x] Relationship
* [ ] Report ^(Deprecated)^
* [x] Results
* [x] Status
* [ ] ScheduledStatus
* [x] Tag
* [ ] Token

=== glitch-soc API

==== Calls

* [x] GET /api/v1/bookmarks
* [x] POST /api/v1/statuses/:id/bookmark
* [x] POST /api/v1/statuses/:id/unbookmark

==== Entities

* [x] `max_toot_chars` in Instance

=== Pleroma API

==== Calls

* [ ] `preview` and `content_type` in POST /api/v1/statuses
* [ ] `no_rich_text`, `hide_followers`, `hide_follows`, `hide_favorites` and
  `show_role` in /api/v1/update_credentials
* [ ] GET /api/pleroma/emoji
* [ ] POST /api/pleroma/follow_import
* [ ] GET /api/pleroma/captcha
* [ ] POST /api/pleroma/delete_account
* [ ] POST /api/account/register
* [ ] POST /api/v1/pleroma/flavour/:flavour
* [ ] GET /api/v1/pleroma/flavour
* [ ] POST /api/pleroma/notifications/read
* [ ] POST /api/v1/pleroma/accounts/:id/subscribe
* [ ] POST /api/v1/pleroma/accounts/:id/unsubscribe
* [ ] GET /api/v1/pleroma/accounts/:id/favourites
* [ ] PUT /api/pleroma/notification_settings
* [ ] GET /api/pleroma/healthcheck
* Admin API
  ** [ ] GET /api/pleroma/admin/users
  ** [ ] DELETE /api/pleroma/admin/user
  ** [ ] POST /api/pleroma/admin/user
  ** [ ] POST /api/pleroma/admin/user/follow
  ** [ ] POST /api/pleroma/admin/user/unfollow
  ** [ ] PATCH /api/pleroma/admin/users/:nickname/toggle_activation
  ** [ ] PUT /api/pleroma/admin/users/tag
  ** [ ] DELETE /api/pleroma/admin/users/tag
  ** [ ] GET /api/pleroma/admin/permission_group/:nickname
  ** [ ] GET /api/pleroma/admin/permission_group/:nickname/:permission_group
  ** [ ] POST /api/pleroma/admin/permission_group/:nickname/:permission_group
  ** [ ] DELETE /api/pleroma/admin/permission_group/:nickname/:permission_group
  ** [ ] PUT /api/pleroma/admin/activation_status/:nickname
  ** [ ] GET /api/pleroma/admin/users/:nickname
  ** [ ] POST /api/pleroma/admin/relay
  ** [ ] DELETE /api/pleroma/admin/relay
  ** [ ] GET /api/pleroma/admin/invite_token
  ** [ ] GET /api/pleroma/admin/invites
  ** [ ] POST /api/pleroma/admin/revoke_invite
  ** [ ] POST /api/pleroma/admin/email_invite
  ** [ ] GET /api/pleroma/admin/password_reset

==== Entities

* `pleroma` object in:
  ** [ ] Status
  ** [ ] Attachment
  ** [ ] Account
  ** [ ] Source
  ** [ ] Notification

== Blocked instances

Instances that are frequently used to hurt marginalized people are blocked from
using this library.

.List of blocked instances:
* https://en.wikipedia.org/wiki/Gab_(social_network)[Gab]
* https://en.wikipedia.org/wiki/Kiwi_Farms[Kiwi Farms]

== Copyright

[source,text]
----
Copyright © 2018, 2019 tastytea <tastytea@tastytea.de>.
License AGPLv3: <https://www.gnu.org/licenses/agpl-3.0.html>.
This program comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
----
