Compare commits

...

18 Commits
0.5.6 ... main

Author SHA1 Message Date
tastytea c48f1dc3d0
add maintenance mode notice
continuous-integration/drone/push Build is passing Details
2022-11-13 06:24:35 +01:00
tastytea 9a25cd9178
add Windows section to readme
Reported-by: Ben S.
2022-11-13 06:19:51 +01:00
tastytea e74828c19e
don't add -fsanitize=undefined if MinGW is used
Reported-by: Ben S.
2022-11-13 06:17:34 +01:00
tastytea 7255df01e0
add support for testing with catch 3
continuous-integration/drone/push Build is passing Details
2022-08-01 14:21:06 +02:00
tastytea 7de644d841
Add repology badge.
continuous-integration/drone/push Build is passing Details
2021-05-17 23:31:50 +02:00
tastytea 52a849870f
Make direction a string_view in answer_type::parse_pagination(). 2021-02-08 17:28:46 +01:00
tastytea aabcb46602
Update .clang-tidy. 2020-11-30 20:52:56 +01:00
tastytea cca3a4a239
Update Gentoo package installation.
continuous-integration/drone/push Build is passing Details
2020-11-29 05:07:04 +01:00
tastytea 5ec7a119dc
Add hyperlink to AUR.
continuous-integration/drone/push Build is passing Details
2020-11-27 14:46:58 +01:00
tastytea cf4302248f
Typo in CI recipe.
continuous-integration/drone/push Build is passing Details
2020-11-20 22:52:57 +01:00
tastytea cadf0d777e
Version bump 0.5.7.
Forgot to bump the version in the CMake recipe, packages couldn't be
built.
2020-11-13 15:07:41 +01:00
tastytea aeb7396961
Generate API documentation with CMake.
continuous-integration/drone/push Build is passing Details
2020-11-13 14:25:22 +01:00
tastytea f4bd5abd01
Fix some warnings.
Avoid copy, initialize members in header, initialize variables.
2020-11-13 14:17:44 +01:00
tastytea c9211e621e
Reformat examples. 2020-11-13 14:05:28 +01:00
tastytea 3a93aec941
Reformat tests. 2020-11-13 14:01:09 +01:00
tastytea 9efc8d2dfd
Reformat source files. 2020-11-13 14:00:03 +01:00
tastytea 8c7493e68e
Reformat header files. 2020-11-13 13:45:59 +01:00
tastytea 63d2497966
Update .clang-tidy, add .clang-format. 2020-11-13 13:41:13 +01:00
40 changed files with 660 additions and 544 deletions

131
.clang-format Normal file
View File

@ -0,0 +1,131 @@
# -*- mode: yaml -*-
# Written for clang-format 10.
# https://releases.llvm.org/10.0.0/tools/clang/docs/ClangFormatStyleOptions.html
---
DisableFormat: false
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
# AlignConsecutiveBitFields: false # clang-format 11
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: false
AlignEscapedNewlines: DontAlign
AlignOperands: true # clang-format 11: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
# AllowShortEnumsOnASingleLine: false # clang-format 11
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: Inline
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping: # If BreakBeforeBraces is set to Custom.
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
# BeforeLambdaBody: true # clang-format 11
# BeforeWhile: true # clang-format 11
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: BeforeComma
BreakStringLiterals: true
ColumnLimit: 80
# CommentPragmas: 'regex'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
FixNamespaceComments: true
ForEachMacros:
- FOREACH
- RANGES_FOR
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Regroup
IncludeCategories: # stdlib headers into own group.
- Regex: '^[^\.]+$'
Priority: 4
# IndentCaseBlocks: false # clang-format 11
IndentCaseLabels: false
# IndentExternBlock: NoIndent # clang-format 11
IndentGotoLabels: false
IndentPPDirectives: AfterHash
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
# MacroBlockBegin: 'string'
# MacroBlockEnd: 'string'
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
# NamespaceMacros: 'string'
PenaltyBreakAssignment: 250
PenaltyBreakBeforeFirstCallParameter: 300
# PenaltyBreakComment: 300
# PenaltyBreakFirstLessLess: 120
# PenaltyBreakString: 1000
# PenaltyBreakTemplateDeclaration: 10
# PenaltyExcessCharacter: 1000000
# PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
# RawStringFormats: # <YAML>
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
# StatementMacros:
# - Q_UNUSED
# - QT_REQUIRE_VERSION
TabWidth: 4
# TypenameMacros:
# - STACK_OF
# - LIST
UseCRLF: false
UseTab: Never
# WhitespaceSensitiveMacros: ['string', 'string'] # clang-format 11
...

View File

@ -1,5 +1,5 @@
# -*- mode: conf; fill-column: 100; -*-
# Written for clang-tidy 9.
# Written for clang-tidy 11.
---
Checks: '*,
@ -25,19 +25,21 @@ Checks: '*,
-hicpp-vararg,
-fuchsia-statically-constructed-objects,
-google-readability-todo,
-modernize-use-trailing-return-type'
CheckOptions: - { key: readability-identifier-naming.ClassCase, value: CamelCase }
# Clashes with constant private member prefix. (const int _var;)
# - { key: readability-identifier-naming.ConstantCase, value: lower_case }
- { key: readability-identifier-naming.EnumCase, value: lower_case }
- { key: readability-identifier-naming.FunctionCase, value: lower_case }
-modernize-use-trailing-return-type,
-fuchsia-multiple-inheritance,
-llvmlibc*'
FormatStyle: file # Use .clang-format.
CheckOptions: # ↓ Clashes with static private member prefix. (static int _var;) ↓
- { key: readability-identifier-naming.VariableCase, value: lower_case }
- { key: readability-identifier-naming.MemberCase, value: lower_case }
- { key: readability-identifier-naming.ParameterCase, value: lower_case }
- { key: readability-identifier-naming.PrivateMemberCase, value: lower_case }
- { key: readability-identifier-naming.PrivateMemberPrefix, value: _ }
- { key: readability-identifier-naming.ProtextedMemberCase, value: lower_case }
- { key: readability-identifier-naming.ProtectedMemberCase, value: lower_case }
- { key: readability-identifier-naming.ProtectedMemberPrefix, value: _ }
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
- { key: readability-identifier-naming.StructCase, value: lower_case }
# Clashes with static private member prefix. (static int _var;)
# - { key: readability-identifier-naming.VariableCase, value: lower_case }
- { key: readability-identifier-naming.EnumCase, value: lower_case }
- { key: readability-identifier-naming.FunctionCase, value: lower_case }
- { key: readability-identifier-naming.ParameterCase, value: lower_case }
...

View File

@ -141,7 +141,7 @@ steps:
- apt-get install -qq build-essential cmake lsb-release
- apt-get install -qq libcurl4-openssl-dev
- rm -rf build && mkdir -p build && cd build
- cmake -G "Unix Makefiles" -SCMAKE_INSTALL_PREFIX=/usr -DWITH_DEB=YES ..
- cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr -DWITH_DEB=YES ..
- make
- make install DESTDIR=install
- make package

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
/build/
/doc/
/update_doc.sh
/examples/example99*

View File

@ -20,7 +20,7 @@ if(NOT ${CMAKE_BUILD_TYPE} MATCHES "Debug")
endif()
project(mastodonpp
VERSION 0.5.5
VERSION 0.5.7
DESCRIPTION "C++ wrapper for the Mastodon and Pleroma APIs."
LANGUAGES CXX)
@ -29,6 +29,7 @@ list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
# Project build options.
option(WITH_TESTS "Compile tests." NO)
option(WITH_EXAMPLES "Compile examples." NO)
option(WITH_DOC "Generate API documentation." NO)
option(WITH_DEB "Prepare for the building of .deb packages." NO)
option(WITH_RPM "Prepare for the building of .rpm packages." NO)
option(WITH_CLANG-TIDY "Check sourcecode with clang-tidy while compiling." NO)
@ -60,4 +61,11 @@ if(WITH_EXAMPLES)
add_subdirectory(examples)
endif()
if(WITH_DOC)
include(cmake/Doxygen.cmake)
enable_doxygen(
"${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/src")
endif()
include(cmake/packages.cmake)

View File

@ -1,27 +0,0 @@
# -*- mode: conf-unix -*-
INPUT = src/ include/
RECURSIVE = YES
STRIP_FROM_INC_PATH = "include"
EXAMPLE_PATH = examples/
EXAMPLE_RECURSIVE = YES
GENERATE_HTML = YES
HTML_OUTPUT = doc/html
GENERATE_LATEX = NO
ALLOW_UNICODE_NAMES = YES
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ALWAYS_DETAILED_SEC = YES
INLINE_INHERITED_MEMB = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 4
MARKDOWN_SUPPORT = YES
AUTOLINK_SUPPORT = YES
INLINE_SIMPLE_STRUCTS = NO
QUIET = NO
WARNINGS = YES
BUILTIN_STL_SUPPORT = YES
VERBATIM_HEADERS = YES
INLINE_SOURCES = YES
SEARCHENGINE = YES
SHOW_FILES = YES

View File

@ -22,6 +22,10 @@
link:{uri-pleroma}[Pleroma] APIs. It replaces
link:{uri-mastodon-cpp}[mastodon-cpp].
[IMPORTANT]
mastodonpp is in maintenance mode. I will continue to fix bugs, but won't add
new features. If you'd like to adopt this project, please get in touch.
We aim to create a library that is comfortable, yet minimal. All API endpoints
from Mastodon and Pleroma are stored in ``enum class``es, to counteract typos
and make your life easier. The network-facing code is built on
@ -79,16 +83,24 @@ link:{uri-reference}/examples.html[More examples] are included in the reference.
== Install
[alt="Packaging status" link=https://repology.org/project/mastodonpp/versions]
image::https://repology.org/badge/vertical-allrepos/mastodonpp.svg[]
=== Gentoo
[source,shell]
--------------------------------------------------------------------------------
eselect repository enable tastytea
eselect repository enable guru
echo 'dev-cpp/mastodonpp' >> /etc/portage/package.accept_keywords/mastodonpp
emaint sync -r tastytea
emaint sync -r guru
emerge -a dev-cpp/mastodonpp
--------------------------------------------------------------------------------
=== Arch
The git-version is available via the AUR:
<https://aur.archlinux.org/packages/mastodonpp-git/>.
=== Debian and Ubuntu
We automatically generate packages for Debian buster (10) and Ubuntu bionic
@ -151,6 +163,7 @@ cmake --build . -- -j$(nproc --ignore=1)
* `-DCMAKE_BUILD_TYPE=Debug` for a debug build.
* `-DWITH_TESTS=YES` if you want to compile the tests.
* `-DWITH_EXAMPLES=YES` if you want to compile the examples.
* `-DWITH_DOC=YES` if you want to generate the API documentation.
* `-DWITH_CLANG-TIDY=YES` to check the sourcecode with
link:{uri-clang-tidy}[clang-tidy] while compiling.
* One of:
@ -159,4 +172,10 @@ cmake --build . -- -j$(nproc --ignore=1)
To create a deb or rpm package, run `make package` after compiling.
===== Windows
mastodonpp has been reported to compile with MinGW GCC, but
`http_method::DELETE` has to be renamed, because Windows headers define a
`DELETE` macro.
include::{uri-base}/raw/branch/main/CONTRIBUTING.adoc[]

View File

@ -1,11 +0,0 @@
#!/bin/sh
project="$(realpath --relative-base=.. .)"
version="$(grep -Eo '[0-9]+.[0-9]+.[0-9]+$' CMakeLists.txt)"
if [[ -f Doxyfile ]]; then
mkdir -p doc
(doxygen -s -g - && cat Doxyfile &&
echo "PROJECT_NAME = ${project}" &&
echo "PROJECT_NUMBER = ${version}") | doxygen -
fi

43
cmake/Doxygen.cmake Normal file
View File

@ -0,0 +1,43 @@
include(GNUInstallDirs)
function(enable_doxygen)
find_package(Doxygen REQUIRED dot)
set(DOXYGEN_RECURSIVE YES)
set(DOXYGEN_STRIP_FROM_INC_PATH "include")
if (WITH_EXAMPLES)
set(DOXYGEN_EXAMPLE_PATH "examples/")
set(DOXYGEN_EXAMPLE_RECURSIVE YES)
endif()
set(DOXYGEN_GENERATE_HTML YES)
set(DOXYGEN_HTML_OUTPUT "doc/html")
set(DOXYGEN_GENERATE_LATEX NO)
set(DOXYGEN_ALLOW_UNICODE_NAMES YES)
set(DOXYGEN_BRIEF_MEMBER_DESC YES)
set(DOXYGEN_REPEAT_BRIEF YES)
set(DOXYGEN_ALWAYS_DETAILED_SEC YES)
set(DOXYGEN_INLINE_INHERITED_MEMB NO)
set(DOXYGEN_INHERIT_DOCS YES)
set(DOXYGEN_SEPARATE_MEMBER_PAGES NO)
set(DOXYGEN_TAB_SIZE 4)
set(DOXYGEN_MARKDOWN_SUPPORT YES)
set(DOXYGEN_AUTOLINK_SUPPORT YES)
set(DOXYGEN_INLINE_SIMPLE_STRUCTS NO)
set(DOXYGEN_QUIET YES)
set(DOXYGEN_WARNINGS YES)
set(DOXYGEN_WARN_IF_UNDOCUMENTED YES)
set(DOXYGEN_BUILTIN_STL_SUPPORT YES)
set(DOXYGEN_VERBATIM_HEADERS YES)
set(DOXYGEN_INLINE_SOURCES YES)
set(DOXYGEN_SEARCHENGINE YES)
set(DOXYGEN_SHOW_FILES YES)
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/doc")
doxygen_add_docs(${PROJECT_NAME}_doxygen "${ARGV}")
# Make sure doxygen is run with every build.
add_custom_target(${PROJECT_NAME}_docs ALL DEPENDS ${PROJECT_NAME}_doxygen)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/html
DESTINATION "${CMAKE_INSTALL_DOCDIR}")
endfunction()

View File

@ -22,7 +22,6 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang"
"-Wdouble-promotion"
"-Wformat=2"
"-ftrapv"
"-fsanitize=undefined"
"-Og"
"-fno-omit-frame-pointer")
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
@ -40,15 +39,21 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang"
endif()
endif()
endif()
if(NOT MINGW)
list(APPEND DEBUG_CXXFLAGS
"-fsanitize=undefined")
endif()
add_compile_options("$<$<CONFIG:Debug>:${DEBUG_CXXFLAGS}>")
set(DEBUG_LDFLAGS
"-fsanitize=undefined")
# add_link_options was introduced in version 3.13.
if(${CMAKE_VERSION} VERSION_LESS 3.13)
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${DEBUG_LDFLAGS}")
else()
add_link_options("$<$<CONFIG:Debug>:${DEBUG_LDFLAGS}>")
if(NOT MINGW)
set(DEBUG_LDFLAGS
"-fsanitize=undefined")
# add_link_options was introduced in version 3.13.
if(${CMAKE_VERSION} VERSION_LESS 3.13)
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${DEBUG_LDFLAGS}")
else()
add_link_options("$<$<CONFIG:Debug>:${DEBUG_LDFLAGS}>")
endif()
endif()
else()
message(STATUS

View File

@ -16,7 +16,7 @@
// Print information about an instance (/api/v1/instance).
#if __has_include("mastodonpp.hpp")
# include "mastodonpp.hpp" // We're building mastodonpp.
# include "mastodonpp.hpp" // We're building mastodonpp.
#else
# include <mastodonpp/mastodonpp.hpp> // We're building outside mastodonpp.
#endif
@ -27,11 +27,11 @@
#include <vector>
namespace masto = mastodonpp;
using std::cout;
using std::cerr;
using std::cout;
using std::endl;
using std::to_string;
using std::string_view;
using std::to_string;
using std::vector;
int main(int argc, char *argv[])

View File

@ -16,7 +16,7 @@
// Print new public events (/api/v1/streaming/public).
#if __has_include("mastodonpp.hpp")
# include "mastodonpp.hpp" // We're building mastodonpp.
# include "mastodonpp.hpp" // We're building mastodonpp.
#else
# include <mastodonpp/mastodonpp.hpp> // We're building outside mastodonpp.
#endif
@ -30,14 +30,14 @@
namespace masto = mastodonpp;
using namespace std::chrono_literals;
using std::cout;
using std::cerr;
using std::cout;
using std::endl;
using std::to_string;
using std::string_view;
using std::thread;
using std::this_thread::sleep_for;
using std::to_string;
using std::vector;
using std::this_thread::sleep_for;
int main(int argc, char *argv[])
{
@ -61,8 +61,10 @@ int main(int argc, char *argv[])
if (answer && answer.body == "OK")
{
// Make a thread, get all public events.
// clang-format off
thread stream_thread{[&]
{
// clang-format on
answer = connection.get(masto::API::v1::streaming_public);
}};
@ -73,8 +75,8 @@ int main(int argc, char *argv[])
for (const auto &event : connection.get_new_events())
{
// Print type of event and the beginning of the data.
cout << event.type << ": "
<< event.data.substr(0, 70) << "" << endl;
cout << event.type << ": " << event.data.substr(0, 70)
<< "" << endl;
}
}

View File

@ -16,7 +16,7 @@
// Post a status (/api/v1/status).
#if __has_include("mastodonpp.hpp")
# include "mastodonpp.hpp" // We're building mastodonpp.
# include "mastodonpp.hpp" // We're building mastodonpp.
#else
# include <mastodonpp/mastodonpp.hpp> // We're building outside mastodonpp.
#endif
@ -27,11 +27,11 @@
#include <vector>
namespace masto = mastodonpp;
using std::cout;
using std::cerr;
using std::cout;
using std::endl;
using std::to_string;
using std::string_view;
using std::to_string;
using std::vector;
int main(int argc, char *argv[])
@ -51,12 +51,12 @@ int main(int argc, char *argv[])
// Set up the parameters.
constexpr auto poll_seconds{60 * 60 * 24 * 2}; // 2 days.
const masto::parametermap parameters
{
{"status", "How is the weather?"},
{"poll[options]", vector<string_view>{"Nice", "not nice"}},
{"poll[expires_in]", to_string(poll_seconds)}
};
const masto::parametermap parameters{{"status", "How is the weather?"},
{"poll[options]",
vector<string_view>{"Nice",
"not nice"}},
{"poll[expires_in]",
to_string(poll_seconds)}};
// Post the status.
auto answer{connection.post(masto::API::v1::statuses, parameters)};

View File

@ -16,7 +16,7 @@
// Post a status (/api/v1/status) with an attachment (/api/v1/media).
#if __has_include("mastodonpp.hpp")
# include "mastodonpp.hpp" // We're building mastodonpp.
# include "mastodonpp.hpp" // We're building mastodonpp.
#else
# include <mastodonpp/mastodonpp.hpp> // We're building outside mastodonpp.
#endif
@ -27,12 +27,12 @@
#include <vector>
namespace masto = mastodonpp;
using std::cout;
using std::cerr;
using std::cout;
using std::endl;
using std::string;
using std::to_string;
using std::string_view;
using std::to_string;
using std::vector;
int main(int argc, char *argv[])
@ -54,10 +54,8 @@ int main(int argc, char *argv[])
// Create attachment.
auto answer{connection.post(masto::API::v1::media,
{
{"file", string("@file:") += filename},
{"description", "Test."}
})};
{{"file", string("@file:") += filename},
{"description", "Test."}})};
// Get the ID of the attachment.
// You normally would use a JSON parser, of course. I don't use one
@ -69,11 +67,9 @@ int main(int argc, char *argv[])
// Post the status. Note that “media_ids” always has to be a vector.
answer = connection.post(masto::API::v1::statuses,
{
{"status", "Attachment test."},
{"media_ids",
vector<string_view>{media_id}}
});
{{"status", "Attachment test."},
{"media_ids",
vector<string_view>{media_id}}});
if (answer)
{
cout << "Successfully posted " << filename << ".\n";

View File

@ -16,7 +16,7 @@
// Update notification settings (/api/pleroma/notification_settings).
#if __has_include("mastodonpp.hpp")
# include "mastodonpp.hpp" // We're building mastodonpp.
# include "mastodonpp.hpp" // We're building mastodonpp.
#else
# include <mastodonpp/mastodonpp.hpp> // We're building outside mastodonpp.
#endif
@ -27,11 +27,11 @@
#include <vector>
namespace masto = mastodonpp;
using std::cout;
using std::cerr;
using std::cout;
using std::endl;
using std::to_string;
using std::string_view;
using std::to_string;
using std::vector;
int main(int argc, char *argv[])
@ -50,14 +50,14 @@ int main(int argc, char *argv[])
masto::Connection connection{instance};
// Update the settings.
const auto answer{connection.put(
masto::API::pleroma::notification_settings,
{
{"followers", "true"},
{"follows", "true"},
{"remote", "true"},
{"local", "true"},
})};
const auto answer{
connection.put(masto::API::pleroma::notification_settings,
{
{"followers", "true"},
{"follows", "true"},
{"remote", "true"},
{"local", "true"},
})};
if (answer)
{
cout << answer << endl;

View File

@ -16,7 +16,7 @@
// Update account display name settings (/api/v1/accounts/update_credentials).
#if __has_include("mastodonpp.hpp")
# include "mastodonpp.hpp" // We're building mastodonpp.
# include "mastodonpp.hpp" // We're building mastodonpp.
#else
# include <mastodonpp/mastodonpp.hpp> // We're building outside mastodonpp.
#endif
@ -27,11 +27,11 @@
#include <vector>
namespace masto = mastodonpp;
using std::cout;
using std::cerr;
using std::cout;
using std::endl;
using std::to_string;
using std::string_view;
using std::to_string;
using std::vector;
int main(int argc, char *argv[])
@ -52,11 +52,9 @@ int main(int argc, char *argv[])
masto::Connection connection{instance};
// Update the settings.
const auto answer{connection.patch(
masto::API::v1::accounts_update_credentials,
{
{"display_name", name}
})};
const auto answer{
connection.patch(masto::API::v1::accounts_update_credentials,
{{"display_name", name}})};
if (answer)
{
cout << "Successfully changed display name.\n";

View File

@ -16,7 +16,7 @@
// Post a status (/api/v1/status), then delete it (/api/v1/statuses/:id).
#if __has_include("mastodonpp.hpp")
# include "mastodonpp.hpp" // We're building mastodonpp.
# include "mastodonpp.hpp" // We're building mastodonpp.
#else
# include <mastodonpp/mastodonpp.hpp> // We're building outside mastodonpp.
#endif
@ -30,13 +30,13 @@
namespace masto = mastodonpp;
using namespace std::chrono_literals;
using std::cout;
using std::cerr;
using std::cout;
using std::endl;
using std::to_string;
using std::string_view;
using std::this_thread::sleep_for;
using std::to_string;
using std::vector;
using std::this_thread::sleep_for;
int main(int argc, char *argv[])
{

View File

@ -16,7 +16,7 @@
// Obtain an access token and verify that it works.
#if __has_include("mastodonpp.hpp")
# include "mastodonpp.hpp" // We're building mastodonpp.
# include "mastodonpp.hpp" // We're building mastodonpp.
#else
# include <mastodonpp/mastodonpp.hpp> // We're building outside mastodonpp.
#endif
@ -28,14 +28,14 @@
#include <vector>
namespace masto = mastodonpp;
using std::exit;
using std::cout;
using std::cerr;
using std::endl;
using std::cin;
using std::cout;
using std::endl;
using std::exit;
using std::string;
using std::to_string;
using std::string_view;
using std::to_string;
using std::vector;
void handle_error(const masto::answer_type &answer);
@ -109,8 +109,8 @@ void handle_error(const masto::answer_type &answer)
else
{
// Network errors like “Couldn't resolve host.”.
cerr << "libcurl error " << to_string(answer.curl_error_code)
<< ": " << answer.error_message << endl;
cerr << "libcurl error " << to_string(answer.curl_error_code) << ": "
<< answer.error_message << endl;
}
exit(1);

View File

@ -17,7 +17,7 @@
// nlohmann-json. <https://github.com/nlohmann/json>
#if __has_include("mastodonpp.hpp")
# include "mastodonpp.hpp" // We're building mastodonpp.
# include "mastodonpp.hpp" // We're building mastodonpp.
#else
# include <mastodonpp/mastodonpp.hpp> // We're building outside mastodonpp.
#endif
@ -26,19 +26,19 @@
#if __has_include(<nlohmann/json.hpp>)
# include <nlohmann/json.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
#include <string_view>
#include <vector>
# include <cstdlib>
# include <iostream>
# include <string>
# include <string_view>
# include <vector>
namespace masto = mastodonpp;
using json = nlohmann::json;
using std::exit;
using std::cout;
using std::cerr;
using std::to_string;
using std::cout;
using std::exit;
using std::string_view;
using std::to_string;
using std::vector;
void handle_error(const masto::answer_type &answer);
@ -60,10 +60,7 @@ int main(int argc, char *argv[])
// Get the last 4 public statuses of the instance.
auto answer{connection.get(masto::API::v1::timelines_public,
{
{"limit", "4"},
{"local", "true"}
})};
{{"limit", "4"}, {"local", "true"}})};
if (answer)
{
// Parse JSON string.
@ -129,8 +126,8 @@ void handle_error(const masto::answer_type &answer)
else
{
// Network errors like “Couldn't resolve host.”.
cerr << "libcurl error " << to_string(answer.curl_error_code)
<< ": " << answer.error_message << '\n';
cerr << "libcurl error " << to_string(answer.curl_error_code) << ": "
<< answer.error_message << '\n';
}
exit(1);
@ -138,11 +135,11 @@ void handle_error(const masto::answer_type &answer)
#else
#include <iostream>
# include <iostream>
int main()
{
std::cout << "Example could not be compiled "
"because nlohmann-json was not found.\n";
"because nlohmann-json was not found.\n";
}
#endif // __has_include(<nlohmann/json.hpp>)
#endif // __has_include(<nlohmann/json.hpp>)

View File

@ -322,7 +322,7 @@ public:
*
* @since 0.1.0
*/
using endpoint_type = variant<v1,v2,oauth,other,pleroma>;
using endpoint_type = variant<v1, v2, oauth, other, pleroma>;
/*!
* @brief Constructs an API object. You should never need this.
@ -339,17 +339,16 @@ public:
*
* @since 0.1.0
*/
[[nodiscard]]
inline string_view to_string_view() const
[[nodiscard]] inline string_view to_string_view() const
{
return _endpoint_map.at(_endpoint);
}
private:
const endpoint_type _endpoint;
static const map<endpoint_type,string_view> _endpoint_map;
static const map<endpoint_type, string_view> _endpoint_map;
};
} // namespace mastodonpp
#endif // MASTODONPP_API_HPP
#endif // MASTODONPP_API_HPP

View File

@ -40,7 +40,7 @@ using std::vector;
*
* @since 0.1.0
*/
using endpoint_variant = variant<API::endpoint_type,string_view>;
using endpoint_variant = variant<API::endpoint_type, string_view>;
/*!
* @brief A stream event.
@ -106,10 +106,10 @@ public:
~Connection() noexcept override = default;
//! Copy assignment operator
Connection& operator=(const Connection &other) = delete;
Connection &operator=(const Connection &other) = delete;
//! Move assignment operator
Connection& operator=(Connection &&other) noexcept = delete;
Connection &operator=(Connection &&other) noexcept = delete;
/*!
* @brief Make a HTTP GET call with parameters.
@ -129,9 +129,8 @@ public:
*
* @since 0.1.0
*/
[[nodiscard]]
answer_type get(const endpoint_variant &endpoint,
const parametermap &parameters);
[[nodiscard]] answer_type get(const endpoint_variant &endpoint,
const parametermap &parameters);
/*!
* @brief Make a HTTP GET call.
@ -145,8 +144,7 @@ public:
*
* @since 0.1.0
*/
[[nodiscard]]
inline answer_type get(const endpoint_variant &endpoint)
[[nodiscard]] inline answer_type get(const endpoint_variant &endpoint)
{
return get(endpoint, {});
}
@ -171,9 +169,8 @@ public:
*
* @since 0.1.0
*/
[[nodiscard]]
answer_type post(const endpoint_variant &endpoint,
const parametermap &parameters);
[[nodiscard]] answer_type post(const endpoint_variant &endpoint,
const parametermap &parameters);
/*!
* @brief Make a HTTP POST call.
@ -182,8 +179,7 @@ public:
*
* @since 0.1.0
*/
[[nodiscard]]
inline answer_type post(const endpoint_variant &endpoint)
[[nodiscard]] inline answer_type post(const endpoint_variant &endpoint)
{
return post(endpoint, {});
}
@ -197,9 +193,8 @@ public:
*
* @since 0.2.0
*/
[[nodiscard]]
answer_type patch(const endpoint_variant &endpoint,
const parametermap &parameters);
[[nodiscard]] answer_type patch(const endpoint_variant &endpoint,
const parametermap &parameters);
/*!
* @brief Make a HTTP PATCH call.
@ -208,8 +203,7 @@ public:
*
* @since 0.2.0
*/
[[nodiscard]]
inline answer_type patch(const endpoint_variant &endpoint)
[[nodiscard]] inline answer_type patch(const endpoint_variant &endpoint)
{
return patch(endpoint, {});
}
@ -223,9 +217,8 @@ public:
*
* @since 0.2.0
*/
[[nodiscard]]
answer_type put(const endpoint_variant &endpoint,
const parametermap &parameters);
[[nodiscard]] answer_type put(const endpoint_variant &endpoint,
const parametermap &parameters);
/*!
* @brief Make a HTTP PUT call.
@ -234,8 +227,7 @@ public:
*
* @since 0.2.0
*/
[[nodiscard]]
inline answer_type put(const endpoint_variant &endpoint)
[[nodiscard]] inline answer_type put(const endpoint_variant &endpoint)
{
return put(endpoint, {});
}
@ -249,9 +241,8 @@ public:
*
* @since 0.2.0
*/
[[nodiscard]]
answer_type del(const endpoint_variant &endpoint,
const parametermap &parameters);
[[nodiscard]] answer_type del(const endpoint_variant &endpoint,
const parametermap &parameters);
/*!
* @brief Make a HTTP DELETE call.
@ -260,8 +251,7 @@ public:
*
* @since 0.2.0
*/
[[nodiscard]]
inline answer_type del(const endpoint_variant &endpoint)
[[nodiscard]] inline answer_type del(const endpoint_variant &endpoint)
{
return del(endpoint, {});
}
@ -291,14 +281,15 @@ public:
{
CURLWrapper::cancel_stream();
}
private:
const Instance &_instance;
const string_view _baseuri;
[[nodiscard]]
string endpoint_to_uri(const endpoint_variant &endpoint) const;
[[nodiscard]] string
endpoint_to_uri(const endpoint_variant &endpoint) const;
};
} // namespace mastodonpp
#endif // MASTODONPP_CONNECTION_HPP
#endif // MASTODONPP_CONNECTION_HPP

View File

@ -17,9 +17,8 @@
#ifndef MASTODONPP_CURL_WRAPPER_HPP
#define MASTODONPP_CURL_WRAPPER_HPP
#include "types.hpp"
#include "curl/curl.h"
#include "types.hpp"
#include <mutex>
#include <string>
@ -39,11 +38,11 @@ using std::string_view;
*/
enum class http_method
{
GET, // NOLINT(readability-identifier-naming)
POST, // NOLINT(readability-identifier-naming)
PATCH, // NOLINT(readability-identifier-naming)
PUT, // NOLINT(readability-identifier-naming)
DELETE // NOLINT(readability-identifier-naming)
GET, // NOLINT(readability-identifier-naming)
POST, // NOLINT(readability-identifier-naming)
PATCH, // NOLINT(readability-identifier-naming)
PUT, // NOLINT(readability-identifier-naming)
DELETE // NOLINT(readability-identifier-naming)
};
/*!
@ -92,10 +91,10 @@ public:
virtual ~CURLWrapper() noexcept;
//! Copy assignment operator
CURLWrapper& operator=(const CURLWrapper &other) = delete;
CURLWrapper &operator=(const CURLWrapper &other) = delete;
//! Move assignment operator
CURLWrapper& operator=(CURLWrapper &&other) noexcept = delete;
CURLWrapper &operator=(CURLWrapper &&other) noexcept = delete;
/*!
* @brief Returns pointer to the CURL easy handle.
@ -162,8 +161,7 @@ public:
*/
void setup_connection_properties(string_view proxy,
string_view access_token,
string_view cainfo,
string_view useragent);
string_view cainfo, string_view useragent);
protected:
/*!
@ -185,17 +183,16 @@ protected:
*
* @since 0.1.0
*/
[[nodiscard]]
answer_type make_request(const http_method &method, string uri,
const parametermap &parameters);
[[nodiscard]] answer_type make_request(const http_method &method,
string uri,
const parametermap &parameters);
/*!
* @brief Returns a reference to the buffer libcurl writes into.
*
* @since 0.1.0
*/
[[nodiscard]]
inline string &get_buffer()
[[nodiscard]] inline string &get_buffer()
{
return _curl_buffer_body;
}
@ -233,7 +230,6 @@ protected:
*/
void set_access_token(string_view access_token);
/*!
* @brief Set path to Certificate Authority (CA) bundle.
*
@ -249,11 +245,11 @@ protected:
virtual void set_useragent(string_view useragent);
private:
CURL *_connection;
char _curl_buffer_error[CURL_ERROR_SIZE];
CURL *_connection{nullptr};
char _curl_buffer_error[CURL_ERROR_SIZE]{'\0'};
string _curl_buffer_headers;
string _curl_buffer_body;
bool _stream_cancelled;
bool _stream_cancelled{false};
/*!
* @brief Initializes curl and sets up connection.
@ -280,7 +276,7 @@ private:
static inline size_t writer_body_wrapper(char *data, size_t sz,
size_t nmemb, void *f)
{
return static_cast<CURLWrapper*>(f)->writer_body(data, sz, nmemb);
return static_cast<CURLWrapper *>(f)->writer_body(data, sz, nmemb);
}
//! @copydoc writer_body
@ -290,7 +286,7 @@ private:
static inline size_t writer_header_wrapper(char *data, size_t sz,
size_t nmemb, void *f)
{
return static_cast<CURLWrapper*>(f)->writer_header(data, sz, nmemb);
return static_cast<CURLWrapper *>(f)->writer_header(data, sz, nmemb);
}
/*!
@ -301,15 +297,15 @@ private:
* @since 0.1.0
*/
int progress(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow);
curl_off_t ultotal, curl_off_t ulnow) const;
//! @copydoc writer_body_wrapper
static inline int progress_wrapper(void *f, void *clientp,
curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow)
{
return static_cast<CURLWrapper*>(f)->progress(clientp, dltotal, dlnow,
ultotal, ulnow);
return static_cast<CURLWrapper *>(f)->progress(clientp, dltotal, dlnow,
ultotal, ulnow);
}
/*!
@ -352,8 +348,8 @@ private:
*
* @since 0.2.0
*/
static void add_mime_part(curl_mime *mime,
string_view name, string_view data);
static void add_mime_part(curl_mime *mime, string_view name,
string_view data);
/*!
* @brief Convert parametermap to `*curl_mime`.
@ -375,4 +371,4 @@ private:
} // namespace mastodonpp
#endif // MASTODONPP_CURL_WRAPPER_HPP
#endif // MASTODONPP_CURL_WRAPPER_HPP

View File

@ -26,9 +26,9 @@
namespace mastodonpp
{
using std::uint16_t;
using std::exception;
using std::string;
using std::uint16_t;
/*!
* @brief Exception for libcurl errors.
@ -77,8 +77,7 @@ public:
*
* @since 0.1.0
*/
[[nodiscard]]
const char *what() const noexcept override;
[[nodiscard]] const char *what() const noexcept override;
private:
const string _message;
@ -87,4 +86,4 @@ private:
} // namespace mastodonpp
#endif // MASTODONPP_EXCEPTIONS_HPP
#endif // MASTODONPP_EXCEPTIONS_HPP

View File

@ -42,9 +42,8 @@ using std::string;
*
* @since 0.4.0
*/
[[nodiscard]]
string unescape_html(string html);
[[nodiscard]] string unescape_html(string html);
} // namespace mastodonpp
#endif // MASTODONPP_HELPERS_HPP
#endif // MASTODONPP_HELPERS_HPP

View File

@ -29,9 +29,9 @@
namespace mastodonpp
{
using std::uint64_t;
using std::string;
using std::string_view;
using std::uint64_t;
using std::vector;
/*!
@ -72,10 +72,10 @@ public:
~Instance() noexcept override = default;
//! Copy assignment operator
Instance& operator=(const Instance &other) = delete;
Instance &operator=(const Instance &other) = delete;
//! Move assignment operator
Instance& operator=(Instance &&other) noexcept = delete;
Instance &operator=(Instance &&other) noexcept = delete;
/*!
* @brief Set the properties of the connection of the calling class up.
@ -98,8 +98,7 @@ public:
*
* @since 0.1.0
*/
[[nodiscard]]
inline string_view get_hostname() const noexcept
[[nodiscard]] inline string_view get_hostname() const noexcept
{
return _hostname;
}
@ -111,8 +110,7 @@ public:
*
* @since 0.1.0
*/
[[nodiscard]]
inline string_view get_baseuri() const noexcept
[[nodiscard]] inline string_view get_baseuri() const noexcept
{
return _baseuri;
}
@ -122,8 +120,7 @@ public:
*
* @since 0.1.0
*/
[[nodiscard]]
inline string_view get_access_token() const noexcept
[[nodiscard]] inline string_view get_access_token() const noexcept
{
return _access_token;
}
@ -153,8 +150,7 @@ public:
*
* @since 0.1.0
*/
[[nodiscard]]
uint64_t get_max_chars() noexcept;
[[nodiscard]] uint64_t get_max_chars() noexcept;
/*! @copydoc CURLWrapper::set_proxy(string_view)
*
@ -176,8 +172,7 @@ public:
*
* @since 0.3.0
*/
[[nodiscard]]
answer_type get_nodeinfo();
[[nodiscard]] answer_type get_nodeinfo();
/*!
* @brief Returns the allowed mime types for statuses.
@ -284,9 +279,9 @@ public:
*
* @since 0.3.0
*/
[[nodiscard]]
answer_type step_1(string_view client_name, string_view scopes,
string_view website);
[[nodiscard]] answer_type step_1(string_view client_name,
string_view scopes,
string_view website);
/*!
* @brief Creates a token via `/oauth/token`.
@ -303,8 +298,7 @@ public:
*
* @since 0.3.0
*/
[[nodiscard]]
answer_type step_2(string_view code);
[[nodiscard]] answer_type step_2(string_view code);
private:
Instance &_instance;
@ -327,4 +321,4 @@ private:
} // namespace mastodonpp
#endif // MASTODONPP_INSTANCE_HPP
#endif // MASTODONPP_INSTANCE_HPP

View File

@ -119,4 +119,4 @@
namespace mastodonpp
{} // namespace mastodonpp
#endif // MASTODONPP_HPP
#endif // MASTODONPP_HPP

View File

@ -31,13 +31,13 @@
namespace mastodonpp
{
using std::uint8_t;
using std::uint16_t;
using std::map;
using std::ostream;
using std::pair;
using std::string;
using std::string_view;
using std::pair;
using std::uint16_t;
using std::uint8_t;
using std::variant;
using std::vector;
@ -60,16 +60,16 @@ using std::vector;
*
* @since 0.1.0
*/
using parametermap =
map<string_view, variant<string_view, vector<string_view>>>;
using parametermap = map<string_view,
variant<string_view, vector<string_view>>>;
/*!
* @brief A single parameter of a parametermap.
*
* @since 0.1.0
*/
using parameterpair =
pair<string_view, variant<string_view, vector<string_view>>>;
using parameterpair = pair<string_view,
variant<string_view, vector<string_view>>>;
/*!
* @brief Return type for Request%s.
@ -138,7 +138,7 @@ struct answer_type
*
* @since 0.1.0
*/
friend ostream &operator <<(ostream &out, const answer_type &answer);
friend ostream &operator<<(ostream &out, const answer_type &answer);
/*!
* @brief Returns the value of a header field.
@ -149,8 +149,7 @@ struct answer_type
*
* @since 0.1.0
*/
[[nodiscard]]
string_view get_header(string_view field) const;
[[nodiscard]] string_view get_header(string_view field) const;
/*!
* @brief Returns the parameters needed for the next entries.
@ -159,8 +158,7 @@ struct answer_type
*
* @since 0.3.0
*/
[[nodiscard]]
inline parametermap next() const
[[nodiscard]] inline parametermap next() const
{
return parse_pagination(true);
}
@ -173,8 +171,7 @@ struct answer_type
*
* @since 0.3.0
*/
[[nodiscard]]
inline parametermap prev() const
[[nodiscard]] inline parametermap prev() const
{
return parse_pagination(false);
}
@ -188,10 +185,9 @@ private:
*
* @since 0.3.0
*/
[[nodiscard]]
parametermap parse_pagination(bool next) const;
[[nodiscard]] parametermap parse_pagination(bool next) const;
};
} // namespace mastodonpp
#endif // MASTODONPP_TYPES_HPP
#endif // MASTODONPP_TYPES_HPP

View File

@ -25,8 +25,7 @@ API::API(const endpoint_type &endpoint)
// TODO: look for a better way.
// NOLINTNEXTLINE(cert-err58-cpp)
const map<API::endpoint_type,string_view> API::_endpoint_map
{
const map<API::endpoint_type, string_view> API::_endpoint_map{
{v1::apps, "/api/v1/apps"},
{v1::apps_verify_credentials, "/api/v1/apps/verify_credentials"},
@ -67,7 +66,7 @@ const map<API::endpoint_type,string_view> API::_endpoint_map
{v1::follow_requests, "/api/v1/follow_requests"},
{v1::follow_requests_id_authorize,
"/api/v1/follow_requests/<ID>/authorize"},
"/api/v1/follow_requests/<ID>/authorize"},
{v1::follow_requests_id_reject, "/api/v1/follow_requests/<ID>/reject"},
{v1::endorsements, "/api/v1/endorsements"},
@ -150,7 +149,7 @@ const map<API::endpoint_type,string_view> API::_endpoint_map
{v1::admin_accounts, "/api/v1/admin/accounts"},
{v1::admin_accounts_id, "/api/v1/admin/accounts/<ID>"},
{v1::admin_accounts_account_id_action,
"/api/v1/admin/accounts/<ACCOUNT_ID>/action"},
"/api/v1/admin/accounts/<ACCOUNT_ID>/action"},
{v1::admin_accounts_id_approve, "/api/v1/admin/accounts/<ID>/approve"},
{v1::admin_accounts_id_reject, "/api/v1/admin/accounts/<ID>/reject"},
{v1::admin_accounts_id_enable, "/api/v1/admin/accounts/<ID>/enable"},
@ -159,39 +158,39 @@ const map<API::endpoint_type,string_view> API::_endpoint_map
{v1::admin_reports, "/api/v1/admin/reports"},
{v1::admin_reports_id, "/api/v1/admin/reports/<ID>"},
{v1::admin_reports_id_assign_to_self,
"/api/v1/admin/reports/<ID>/assign_to_self"},
"/api/v1/admin/reports/<ID>/assign_to_self"},
{v1::admin_reports_id_unassign, "/api/v1/admin/reports/<ID>/unassign"},
{v1::admin_reports_id_resolve, "/api/v1/admin/reports/<ID>/resolve"},
{v1::admin_reports_id_reopen, "/api/v1/admin/reports/<ID>/reopen"},
{v1::pleroma_notifications_read, " /api/v1/pleroma/notifications/read"},
{v1::pleroma_accounts_id_subscribe,
"/api/v1/pleroma/accounts/<ID>/subscribe"},
"/api/v1/pleroma/accounts/<ID>/subscribe"},
{v1::pleroma_accounts_id_unsubscribe,
"/api/v1/pleroma/accounts/<ID>/unsubscribe"},
"/api/v1/pleroma/accounts/<ID>/unsubscribe"},
{v1::pleroma_accounts_id_favourites,
"/api/v1/pleroma/accounts/<ID>/favourites"},
"/api/v1/pleroma/accounts/<ID>/favourites"},
{v1::pleroma_accounts_update_avatar,
"/api/v1/pleroma/accounts/update_avatar"},
"/api/v1/pleroma/accounts/update_avatar"},
{v1::pleroma_accounts_update_banner,
"/api/v1/pleroma/accounts/update_banner"},
"/api/v1/pleroma/accounts/update_banner"},
{v1::pleroma_accounts_update_background,
"/api/v1/pleroma/accounts/update_background"},
"/api/v1/pleroma/accounts/update_background"},
{v1::pleroma_accounts_confirmation_resend,
"/api/v1/pleroma/accounts/confirmation_resend"},
"/api/v1/pleroma/accounts/confirmation_resend"},
{v1::pleroma_mascot, "/api/v1/pleroma/mascot"},
{v1::pleroma_conversations_id_statuses,
"/api/v1/pleroma/conversations/<ID>/statuses"},
"/api/v1/pleroma/conversations/<ID>/statuses"},
{v1::pleroma_conversations_id, "/api/v1/pleroma/conversations/<ID>"},
{v1::pleroma_conversations_id_read,
"/api/v1/pleroma/conversations/<ID>/read"},
"/api/v1/pleroma/conversations/<ID>/read"},
{v1::pleroma_accounts_id_scrobbles,
"/api/v1/pleroma/accounts/<ID>/scrobbles"},
"/api/v1/pleroma/accounts/<ID>/scrobbles"},
{v1::pleroma_scrobble, "/api/v1/pleroma/scrobble"},
{v1::pleroma_statuses_id_reactions_emoji,
"/api/v1/pleroma/statuses/<ID>/reactions/<EMOJI>"},
"/api/v1/pleroma/statuses/<ID>/reactions/<EMOJI>"},
{v1::pleroma_statuses_id_reactions,
"/api/v1/pleroma/statuses/<ID>/reactions"},
"/api/v1/pleroma/statuses/<ID>/reactions"},
{v2::search, "/api/v2/search"},
@ -206,66 +205,66 @@ const map<API::endpoint_type,string_view> API::_endpoint_map
{pleroma::admin_users_follow, "/api/pleroma/admin/users/follow"},
{pleroma::admin_users_unfollow, "/api/pleroma/admin/users/unfollow"},
{pleroma::admin_users_nickname_toggle_activation,
"/api/pleroma/admin/users/<NICKNAME>/toggle_activation"},
"/api/pleroma/admin/users/<NICKNAME>/toggle_activation"},
{pleroma::admin_users_tag, "/api/pleroma/admin/users/tag"},
{pleroma::admin_users_nickname_permission_group,
"/api/pleroma/admin/users/<NICKNAME>/permission_group"},
"/api/pleroma/admin/users/<NICKNAME>/permission_group"},
{pleroma::admin_users_nickname_permission_group_permission_group,
"/api/pleroma/admin/users/<NICKNAME>"
"/permission_group/<PERMISSION_GROUP>"},
"/api/pleroma/admin/users/<NICKNAME>"
"/permission_group/<PERMISSION_GROUP>"},
{pleroma::admin_users_permission_group_permission_group,
"/api/pleroma/admin/users/permission_group/<PERMISSION_GROUP>"},
"/api/pleroma/admin/users/permission_group/<PERMISSION_GROUP>"},
{pleroma::admin_users_activate, "/api/pleroma/admin/users/activate"},
{pleroma::admin_users_deactivate, "/api/pleroma/admin/users/deactivate"},
{pleroma::admin_users_nickname_or_id,
"/api/pleroma/admin/users/<NICKNAME_OR_ID>"},
"/api/pleroma/admin/users/<NICKNAME_OR_ID>"},
{pleroma::admin_users_nickname_or_id_statuses,
"/api/pleroma/admin/users/<NICKNAME_OR_ID>/statuses"},
"/api/pleroma/admin/users/<NICKNAME_OR_ID>/statuses"},
{pleroma::admin_instances_instance_statuses,
"/api/pleroma/admin/instances/<INSTANCE>/statuses"},
"/api/pleroma/admin/instances/<INSTANCE>/statuses"},
{pleroma::admin_statuses, "/api/pleroma/admin/statuses"},
{pleroma::admin_relay, "/api/pleroma/admin/relay"},
{pleroma::admin_users_invite_token,
"/api/pleroma/admin/users/invite_token"},
"/api/pleroma/admin/users/invite_token"},
{pleroma::admin_users_invites, "/api/pleroma/admin/users/invites"},
{pleroma::admin_users_revoke_invite,
"/api/pleroma/admin/users/revoke_invite"},
"/api/pleroma/admin/users/revoke_invite"},
{pleroma::admin_users_email_invite,
"/api/pleroma/admin/users/email_invite"},
"/api/pleroma/admin/users/email_invite"},
{pleroma::admin_users_nickname_password_reset,
"/api/pleroma/admin/users/<NICKNAME>/password_reset"},
"/api/pleroma/admin/users/<NICKNAME>/password_reset"},
{pleroma::admin_users_nickname_update_credentials,
"/api/pleroma/admin/users/<NICKNAME>/update_credentials"},
"/api/pleroma/admin/users/<NICKNAME>/update_credentials"},
{pleroma::admin_users_force_password_reset,
"/api/pleroma/admin/users/force_password_reset"},
"/api/pleroma/admin/users/force_password_reset"},
{pleroma::admin_reports, "/api/pleroma/admin/reports"},
{pleroma::admin_grouped_reports, "/api/pleroma/admin/grouped_reports"},
{pleroma::admin_reports_id, "/api/pleroma/admin/reports/<ID>"},
{pleroma::admin_reports_id_notes, "/api/pleroma/admin/reports/<ID>/notes"},
{pleroma::admin_reports_report_id_notes_id,
"/api/pleroma/admin/reports/<REPORT_ID>/notes/<ID>"},
"/api/pleroma/admin/reports/<REPORT_ID>/notes/<ID>"},
{pleroma::admin_statuses_id, "/api/pleroma/admin/statuses/<ID>"},
{pleroma::admin_restart, "/api/pleroma/admin/restart"},
{pleroma::admin_config, "/api/pleroma/admin/config"},
{pleroma::admin_config_descriptions,
"/api/pleroma/admin/config/descriptions"},
"/api/pleroma/admin/config/descriptions"},
{pleroma::admin_moderation_log, "/api/pleroma/admin/moderation_log"},
{pleroma::admin_reload_emoji, "/api/pleroma/admin/reload_emoji"},
{pleroma::admin_users_confirm_email,
"/api/pleroma/admin/users/confirm_email"},
"/api/pleroma/admin/users/confirm_email"},
{pleroma::admin_users_resend_confirm_email,
"/api/pleroma/admin/users/resend_confirm_email"},
"/api/pleroma/admin/users/resend_confirm_email"},
{pleroma::admin_stats, "/api/pleroma/admin/stats"},
{pleroma::admin_users_nickname, "/api/pleroma/admin/users/<NICKNAME>"},
{pleroma::admin_users_nickname_activation_status,
"/api/pleroma/admin/users/<NICKNAME>/activation_status"},
"/api/pleroma/admin/users/<NICKNAME>/activation_status"},
{pleroma::admin_reports_id_respond,
"/api/pleroma/admin/reports/<ID>/respond"},
"/api/pleroma/admin/reports/<ID>/respond"},
{pleroma::admin_config_migrate_to_db,
"/api/pleroma/admin/config/migrate_to_db"},
"/api/pleroma/admin/config/migrate_to_db"},
{pleroma::admin_config_migrate_from_db,
"/api/pleroma/admin/config/migrate_from_db"},
"/api/pleroma/admin/config/migrate_from_db"},
{pleroma::emoji, "/api/pleroma/emoji"},
{pleroma::follow_import, "/api/pleroma/follow_import"},
@ -278,18 +277,16 @@ const map<API::endpoint_type,string_view> API::_endpoint_map
{pleroma::emoji_packs, "/api/pleroma/emoji/packs"},
{pleroma::emoji_packs_name, "/api/pleroma/emoji/packs/<NAME>"},
{pleroma::emoji_packs_name_update_file,
"/api/pleroma/emoji/packs/<NAME>/update_file"},
"/api/pleroma/emoji/packs/<NAME>/update_file"},
{pleroma::emoji_packs_name_update_metadata,
"/api/pleroma/emoji/packs/<NAME>/update_metadata"},
"/api/pleroma/emoji/packs/<NAME>/update_metadata"},
{pleroma::emoji_packs_download_from,
"/api/pleroma/emoji/packs/download_from"},
{pleroma::emoji_packs_list_from,
"/api/pleroma/emoji/packs/list_from"},
"/api/pleroma/emoji/packs/download_from"},
{pleroma::emoji_packs_list_from, "/api/pleroma/emoji/packs/list_from"},
{pleroma::emoji_packs_name_download_shared,
"/api/pleroma/emoji/packs/<NAME>/download_shared"},
"/api/pleroma/emoji/packs/<NAME>/download_shared"},
{pleroma::account_register, "/api/pleroma/account/register"},
};
} // namespace mastodonpp

View File

@ -25,8 +25,8 @@ string Connection::endpoint_to_uri(const endpoint_variant &endpoint) const
{
if (holds_alternative<API::endpoint_type>(endpoint))
{
return string(_baseuri)
+= API{std::get<API::endpoint_type>(endpoint)}.to_string_view();
return string(_baseuri) += API{std::get<API::endpoint_type>(endpoint)}
.to_string_view();
}
return string(_baseuri) += std::get<string_view>(endpoint);
}
@ -34,43 +34,43 @@ string Connection::endpoint_to_uri(const endpoint_variant &endpoint) const
answer_type Connection::get(const endpoint_variant &endpoint,
const parametermap &parameters)
{
return make_request(http_method::GET,
endpoint_to_uri(endpoint), parameters);
return make_request(http_method::GET, endpoint_to_uri(endpoint),
parameters);
}
answer_type Connection::post(const endpoint_variant &endpoint,
const parametermap &parameters)
{
return make_request(http_method::POST,
endpoint_to_uri(endpoint), parameters);
return make_request(http_method::POST, endpoint_to_uri(endpoint),
parameters);
}
answer_type Connection::patch(const endpoint_variant &endpoint,
const parametermap &parameters)
{
return make_request(http_method::PATCH,
endpoint_to_uri(endpoint), parameters);
return make_request(http_method::PATCH, endpoint_to_uri(endpoint),
parameters);
}
answer_type Connection::put(const endpoint_variant &endpoint,
const parametermap &parameters)
{
return make_request(http_method::PUT,
endpoint_to_uri(endpoint), parameters);
return make_request(http_method::PUT, endpoint_to_uri(endpoint),
parameters);
}
answer_type Connection::del(const endpoint_variant &endpoint,
const parametermap &parameters)
{
return make_request(http_method::DELETE,
endpoint_to_uri(endpoint), parameters);
return make_request(http_method::DELETE, endpoint_to_uri(endpoint),
parameters);
}
string Connection::get_new_stream_contents()
{
_buffer_mutex.lock();
auto &buffer{get_buffer()};
const string buffer_copy{buffer};
string buffer_copy{buffer};
buffer.clear();
_buffer_mutex.unlock();
return buffer_copy;

View File

@ -15,6 +15,7 @@
*/
#include "curl_wrapper.hpp"
#include "exceptions.hpp"
#include "log.hpp"
#include "version.hpp"
@ -28,15 +29,15 @@
namespace mastodonpp
{
using std::any_of;
using std::array; // NOLINT(misc-unused-using-decls)
using std::atomic;
using std::get;
using std::holds_alternative;
using std::any_of;
using std::transform;
using std::array; // NOLINT(misc-unused-using-decls)
using std::atomic;
using std::toupper;
using std::uint8_t;
using std::transform;
using std::uint16_t;
using std::uint8_t;
// No one will ever need more than 65535 connections. 😉
static atomic<uint16_t> curlwrapper_instances{0};
@ -55,17 +56,11 @@ void CURLWrapper::init()
}
CURLWrapper::CURLWrapper()
: _connection{}
, _curl_buffer_error{}
, _stream_cancelled{false}
{
init();
}
CURLWrapper::CURLWrapper(const CURLWrapper &)
: _connection{}
, _curl_buffer_error{}
, _stream_cancelled{false}
{
init();
}
@ -89,7 +84,7 @@ answer_type CURLWrapper::make_request(const http_method &method, string uri,
_curl_buffer_headers.clear();
_curl_buffer_body.clear();
CURLcode code;
CURLcode code{CURLE_OK};
switch (method)
{
case http_method::GET:
@ -185,7 +180,7 @@ answer_type CURLWrapper::make_request(const http_method &method, string uri,
if (code == CURLE_OK
|| (code == CURLE_ABORTED_BY_CALLBACK && _stream_cancelled))
{
long http_status; // NOLINT(google-runtime-int)
long http_status{0}; // NOLINT(google-runtime-int)
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
curl_easy_getinfo(_connection, CURLINFO_RESPONSE_CODE, &http_status);
answer.http_status = static_cast<uint16_t>(http_status);
@ -250,11 +245,11 @@ void CURLWrapper::set_access_token(const string_view access_token)
if (code != CURLE_OK)
{
throw CURLException{code, "Could not set authorization token.",
_curl_buffer_error};
_curl_buffer_error};
}
#if (LIBCURL_VERSION_NUM < 0x073d00) // libcurl < 7.61.0.
#define CURLAUTH_BEARER CURLAUTH_ANY
# define CURLAUTH_BEARER CURLAUTH_ANY
#endif
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-signed-bitwise)
@ -262,7 +257,7 @@ void CURLWrapper::set_access_token(const string_view access_token)
if (code != CURLE_OK)
{
throw CURLException{code, "Could not set authorization token.",
_curl_buffer_error};
_curl_buffer_error};
}
debuglog << "Set authorization token.\n";
@ -280,20 +275,20 @@ void CURLWrapper::set_cainfo(const string_view path)
void CURLWrapper::set_useragent(const string_view useragent)
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
CURLcode code{curl_easy_setopt(_connection, CURLOPT_USERAGENT,
useragent.data())};
CURLcode code{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
curl_easy_setopt(_connection, CURLOPT_USERAGENT, useragent.data())};
if (code != CURLE_OK)
{
throw CURLException{code, "Failed to set User-Agent",
_curl_buffer_error};
_curl_buffer_error};
}
debuglog << "Set User-Agent to: " << useragent << '\n';
}
size_t CURLWrapper::writer_body(char *data, size_t size, size_t nmemb)
{
if(data == nullptr)
if (data == nullptr)
{
return 0;
}
@ -307,7 +302,7 @@ size_t CURLWrapper::writer_body(char *data, size_t size, size_t nmemb)
size_t CURLWrapper::writer_header(char *data, size_t size, size_t nmemb)
{
if(data == nullptr)
if (data == nullptr)
{
return 0;
}
@ -317,8 +312,8 @@ size_t CURLWrapper::writer_header(char *data, size_t size, size_t nmemb)
return size * nmemb;
}
int CURLWrapper::progress(void *, curl_off_t , curl_off_t ,
curl_off_t , curl_off_t )
int CURLWrapper::progress(void *, curl_off_t, curl_off_t, curl_off_t,
curl_off_t) const
{
if (_stream_cancelled)
{
@ -371,21 +366,25 @@ void CURLWrapper::setup_curl()
bool CURLWrapper::replace_parameter_in_uri(string &uri,
const parameterpair &parameter)
{
static constexpr array replace
{
"id", "nickname", "nickname_or_id", "account_id", "list_id",
"hashtag", "permission_group", "instance", "report_id", "name",
"emoji"
};
static constexpr array replace{"id",
"nickname",
"nickname_or_id",
"account_id",
"list_id",
"hashtag",
"permission_group",
"instance",
"report_id",
"name",
"emoji"};
if (any_of(replace.begin(), replace.end(),
[&parameter](const auto &s) { return s == parameter.first; }))
{
const string searchstring{[&parameter]
{
const string searchstring{[&parameter] {
string s{"<"};
s += parameter.first;
transform(s.begin(), s.end(), s.begin(),
[](const unsigned char c){ return toupper(c); });
[](const unsigned char c) { return toupper(c); });
return s;
}()};
const auto pos{uri.find(searchstring)};
@ -441,8 +440,8 @@ void CURLWrapper::add_parameters_to_uri(string &uri,
}
}
void CURLWrapper::add_mime_part(curl_mime *mime,
string_view name, string_view data)
void CURLWrapper::add_mime_part(curl_mime *mime, string_view name,
string_view data)
{
curl_mimepart *part{curl_mime_addpart(mime)};
if (part == nullptr)

View File

@ -21,8 +21,8 @@
namespace mastodonpp
{
using std::to_string;
using std::move;
using std::to_string;
CURLException::CURLException(const CURLcode &error, string message)
: error_code{error}

View File

@ -26,15 +26,15 @@
namespace mastodonpp
{
using std::stoul;
using std::codecvt_utf8;
using std::wstring_convert;
using std::map;
using std::move;
using std::regex;
using std::regex_search;
using std::smatch;
using std::stoul;
using std::string_view;
using std::move;
using std::wstring_convert;
string unescape_html(string html)
{
@ -43,145 +43,100 @@ string unescape_html(string html)
// Source: https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_
// entity_references#Character_entity_references_in_HTML
const map<string_view, char32_t> names
{
{ "exclamation", 0x0021 }, { "quot", 0x0022 },
{ "percent", 0x0025 }, { "amp", 0x0026 },
{ "apos", 0x0027 }, { "add", 0x002B },
{ "lt", 0x003C }, { "equal", 0x003D },
{ "gt", 0x003E }, { "nbsp", 0x00A0 },
{ "iexcl", 0x00A1 }, { "cent", 0x00A2 },
{ "pound", 0x00A3 }, { "curren", 0x00A4 },
{ "yen", 0x00A5 }, { "brvbar", 0x00A6 },
{ "sect", 0x00A7 }, { "uml", 0x00A8 },
{ "copy", 0x00A9 }, { "ordf", 0x00AA },
{ "laquo", 0x00AB }, { "not", 0x00AC },
{ "shy", 0x00AD }, { "reg", 0x00AE },
{ "macr", 0x00AF }, { "deg", 0x00B0 },
{ "plusmn", 0x00B1 }, { "sup2", 0x00B2 },
{ "sup3", 0x00B3 }, { "acute", 0x00B4 },
{ "micro", 0x00B5 }, { "para", 0x00B6 },
{ "middot", 0x00B7 }, { "cedil", 0x00B8 },
{ "sup1", 0x00B9 }, { "ordm", 0x00BA },
{ "raquo", 0x00BB }, { "frac14", 0x00BC },
{ "frac12", 0x00BD }, { "frac34", 0x00BE },
{ "iquest", 0x00BF }, { "Agrave", 0x00C0 },
{ "Aacute", 0x00C1 }, { "Acirc", 0x00C2 },
{ "Atilde", 0x00C3 }, { "Auml", 0x00C4 },
{ "Aring", 0x00C5 }, { "AElig", 0x00C6 },
{ "Ccedil", 0x00C7 }, { "Egrave", 0x00C8 },
{ "Eacute", 0x00C9 }, { "Ecirc", 0x00CA },
{ "Euml", 0x00CB }, { "Igrave", 0x00CC },
{ "Iacute", 0x00CD }, { "Icirc", 0x00CE },
{ "Iuml", 0x00CF }, { "ETH", 0x00D0 },
{ "Ntilde", 0x00D1 }, { "Ograve", 0x00D2 },
{ "Oacute", 0x00D3 }, { "Ocirc", 0x00D4 },
{ "Otilde", 0x00D5 }, { "Ouml", 0x00D6 },
{ "times", 0x00D7 }, { "Oslash", 0x00D8 },
{ "Ugrave", 0x00D9 }, { "Uacute", 0x00DA },
{ "Ucirc", 0x00DB }, { "Uuml", 0x00DC },
{ "Yacute", 0x00DD }, { "THORN", 0x00DE },
{ "szlig", 0x00DF }, { "agrave", 0x00E0 },
{ "aacute", 0x00E1 }, { "acirc", 0x00E2 },
{ "atilde", 0x00E3 }, { "auml", 0x00E4 },
{ "aring", 0x00E5 }, { "aelig", 0x00E6 },
{ "ccedil", 0x00E7 }, { "egrave", 0x00E8 },
{ "eacute", 0x00E9 }, { "ecirc", 0x00EA },
{ "euml", 0x00EB }, { "igrave", 0x00EC },
{ "iacute", 0x00ED }, { "icirc", 0x00EE },
{ "iuml", 0x00EF }, { "eth", 0x00F0 },
{ "ntilde", 0x00F1 }, { "ograve", 0x00F2 },
{ "oacute", 0x00F3 }, { "ocirc", 0x00F4 },
{ "otilde", 0x00F5 }, { "ouml", 0x00F6 },
{ "divide", 0x00F7 }, { "oslash", 0x00F8 },
{ "ugrave", 0x00F9 }, { "uacute", 0x00FA },
{ "ucirc", 0x00FB }, { "uuml", 0x00FC },
{ "yacute", 0x00FD }, { "thorn", 0x00FE },
{ "yuml", 0x00FF }, { "OElig", 0x0152 },
{ "oelig", 0x0153 }, { "Scaron", 0x0160 },
{ "scaron", 0x0161 }, { "Yuml", 0x0178 },
{ "fnof", 0x0192 }, { "circ", 0x02C6 },
{ "tilde", 0x02DC }, { "Alpha", 0x0391 },
{ "Beta", 0x0392 }, { "Gamma", 0x0393 },
{ "Delta", 0x0394 }, { "Epsilon", 0x0395 },
{ "Zeta", 0x0396 }, { "Eta", 0x0397 },
{ "Theta", 0x0398 }, { "Iota", 0x0399 },
{ "Kappa", 0x039A }, { "Lambda", 0x039B },
{ "Mu", 0x039C }, { "Nu", 0x039D },
{ "Xi", 0x039E }, { "Omicron", 0x039F },
{ "Pi", 0x03A0 }, { "Rho", 0x03A1 },
{ "Sigma", 0x03A3 }, { "Tau", 0x03A4 },
{ "Upsilon", 0x03A5 }, { "Phi", 0x03A6 },
{ "Chi", 0x03A7 }, { "Psi", 0x03A8 },
{ "Omega", 0x03A9 }, { "alpha", 0x03B1 },
{ "beta", 0x03B2 }, { "gamma", 0x03B3 },
{ "delta", 0x03B4 }, { "epsilon", 0x03B5 },
{ "zeta", 0x03B6 }, { "eta", 0x03B7 },
{ "theta", 0x03B8 }, { "iota", 0x03B9 },
{ "kappa", 0x03BA }, { "lambda", 0x03BB },
{ "mu", 0x03BC }, { "nu", 0x03BD },
{ "xi", 0x03BE }, { "omicron", 0x03BF },
{ "pi", 0x03C0 }, { "rho", 0x03C1 },
{ "sigmaf", 0x03C2 }, { "sigma", 0x03C3 },
{ "tau", 0x03C4 }, { "upsilon", 0x03C5 },
{ "phi", 0x03C6 }, { "chi", 0x03C7 },
{ "psi", 0x03C8 }, { "omega", 0x03C9 },
{ "thetasym", 0x03D1 }, { "upsih", 0x03D2 },
{ "piv", 0x03D6 }, { "ensp", 0x2002 },
{ "emsp", 0x2003 }, { "thinsp", 0x2009 },
{ "zwnj", 0x200C }, { "zwj", 0x200D },
{ "lrm", 0x200E }, { "rlm", 0x200F },
{ "ndash", 0x2013 }, { "mdash", 0x2014 },
{ "horbar", 0x2015 }, { "lsquo", 0x2018 },
{ "rsquo", 0x2019 }, { "sbquo", 0x201A },
{ "ldquo", 0x201C }, { "rdquo", 0x201D },
{ "bdquo", 0x201E }, { "dagger", 0x2020 },
{ "Dagger", 0x2021 }, { "bull", 0x2022 },
{ "hellip", 0x2026 }, { "permil", 0x2030 },
{ "prime", 0x2032 }, { "Prime", 0x2033 },
{ "lsaquo", 0x2039 }, { "rsaquo", 0x203A },
{ "oline", 0x203E }, { "frasl", 0x2044 },
{ "euro", 0x20AC }, { "image", 0x2111 },
{ "weierp", 0x2118 }, { "real", 0x211C },
{ "trade", 0x2122 }, { "alefsym", 0x2135 },
{ "larr", 0x2190 }, { "uarr", 0x2191 },
{ "rarr", 0x2192 }, { "darr", 0x2193 },
{ "harr", 0x2194 }, { "crarr", 0x21B5 },
{ "lArr", 0x21D0 }, { "uArr", 0x21D1 },
{ "rArr", 0x21D2 }, { "dArr", 0x21D3 },
{ "hArr", 0x21D4 }, { "forall", 0x2200 },
{ "part", 0x2202 }, { "exist", 0x2203 },
{ "empty", 0x2205 }, { "nabla", 0x2207 },
{ "isin", 0x2208 }, { "notin", 0x2209 },
{ "ni", 0x220B }, { "prod", 0x220F },
{ "sum", 0x2211 }, { "minus", 0x2212 },
{ "lowast", 0x2217 }, { "radic", 0x221A },
{ "prop", 0x221D }, { "infin", 0x221E },
{ "ang", 0x2220 }, { "and", 0x2227 },
{ "or", 0x2228 }, { "cap", 0x2229 },
{ "cup", 0x222A }, { "int", 0x222B },
{ "there4", 0x2234 }, { "sim", 0x223C },
{ "cong", 0x2245 }, { "asymp", 0x2248 },
{ "ne", 0x2260 }, { "equiv", 0x2261 },
{ "le", 0x2264 }, { "ge", 0x2265 },
{ "sub", 0x2282 }, { "sup", 0x2283 },
{ "nsub", 0x2284 }, { "sube", 0x2286 },
{ "supe", 0x2287 }, { "oplus", 0x2295 },
{ "otimes", 0x2297 }, { "perp", 0x22A5 },
{ "sdot", 0x22C5 }, { "lceil", 0x2308 },
{ "rceil", 0x2309 }, { "lfloor", 0x230A },
{ "rfloor", 0x230B }, { "lang", 0x2329 },
{ "rang", 0x232A }, { "loz", 0x25CA },
{ "spades", 0x2660 }, { "clubs", 0x2663 },
{ "hearts", 0x2665 }, { "diams", 0x2666 }
};
const map<string_view, char32_t>
names{{"exclamation", 0x0021}, {"quot", 0x0022}, {"percent", 0x0025},
{"amp", 0x0026}, {"apos", 0x0027}, {"add", 0x002B},
{"lt", 0x003C}, {"equal", 0x003D}, {"gt", 0x003E},
{"nbsp", 0x00A0}, {"iexcl", 0x00A1}, {"cent", 0x00A2},
{"pound", 0x00A3}, {"curren", 0x00A4}, {"yen", 0x00A5},
{"brvbar", 0x00A6}, {"sect", 0x00A7}, {"uml", 0x00A8},
{"copy", 0x00A9}, {"ordf", 0x00AA}, {"laquo", 0x00AB},
{"not", 0x00AC}, {"shy", 0x00AD}, {"reg", 0x00AE},
{"macr", 0x00AF}, {"deg", 0x00B0}, {"plusmn", 0x00B1},
{"sup2", 0x00B2}, {"sup3", 0x00B3}, {"acute", 0x00B4},
{"micro", 0x00B5}, {"para", 0x00B6}, {"middot", 0x00B7},
{"cedil", 0x00B8}, {"sup1", 0x00B9}, {"ordm", 0x00BA},
{"raquo", 0x00BB}, {"frac14", 0x00BC}, {"frac12", 0x00BD},
{"frac34", 0x00BE}, {"iquest", 0x00BF}, {"Agrave", 0x00C0},
{"Aacute", 0x00C1}, {"Acirc", 0x00C2}, {"Atilde", 0x00C3},
{"Auml", 0x00C4}, {"Aring", 0x00C5}, {"AElig", 0x00C6},
{"Ccedil", 0x00C7}, {"Egrave", 0x00C8}, {"Eacute", 0x00C9},
{"Ecirc", 0x00CA}, {"Euml", 0x00CB}, {"Igrave", 0x00CC},
{"Iacute", 0x00CD}, {"Icirc", 0x00CE}, {"Iuml", 0x00CF},
{"ETH", 0x00D0}, {"Ntilde", 0x00D1}, {"Ograve", 0x00D2},
{"Oacute", 0x00D3}, {"Ocirc", 0x00D4}, {"Otilde", 0x00D5},
{"Ouml", 0x00D6}, {"times", 0x00D7}, {"Oslash", 0x00D8},
{"Ugrave", 0x00D9}, {"Uacute", 0x00DA}, {"Ucirc", 0x00DB},
{"Uuml", 0x00DC}, {"Yacute", 0x00DD}, {"THORN", 0x00DE},
{"szlig", 0x00DF}, {"agrave", 0x00E0}, {"aacute", 0x00E1},
{"acirc", 0x00E2}, {"atilde", 0x00E3}, {"auml", 0x00E4},
{"aring", 0x00E5}, {"aelig", 0x00E6}, {"ccedil", 0x00E7},
{"egrave", 0x00E8}, {"eacute", 0x00E9}, {"ecirc", 0x00EA},
{"euml", 0x00EB}, {"igrave", 0x00EC}, {"iacute", 0x00ED},
{"icirc", 0x00EE}, {"iuml", 0x00EF}, {"eth", 0x00F0},
{"ntilde", 0x00F1}, {"ograve", 0x00F2}, {"oacute", 0x00F3},
{"ocirc", 0x00F4}, {"otilde", 0x00F5}, {"ouml", 0x00F6},
{"divide", 0x00F7}, {"oslash", 0x00F8}, {"ugrave", 0x00F9},
{"uacute", 0x00FA}, {"ucirc", 0x00FB}, {"uuml", 0x00FC},
{"yacute", 0x00FD}, {"thorn", 0x00FE}, {"yuml", 0x00FF},
{"OElig", 0x0152}, {"oelig", 0x0153}, {"Scaron", 0x0160},
{"scaron", 0x0161}, {"Yuml", 0x0178}, {"fnof", 0x0192},
{"circ", 0x02C6}, {"tilde", 0x02DC}, {"Alpha", 0x0391},
{"Beta", 0x0392}, {"Gamma", 0x0393}, {"Delta", 0x0394},
{"Epsilon", 0x0395}, {"Zeta", 0x0396}, {"Eta", 0x0397},
{"Theta", 0x0398}, {"Iota", 0x0399}, {"Kappa", 0x039A},
{"Lambda", 0x039B}, {"Mu", 0x039C}, {"Nu", 0x039D},
{"Xi", 0x039E}, {"Omicron", 0x039F}, {"Pi", 0x03A0},
{"Rho", 0x03A1}, {"Sigma", 0x03A3}, {"Tau", 0x03A4},
{"Upsilon", 0x03A5}, {"Phi", 0x03A6}, {"Chi", 0x03A7},
{"Psi", 0x03A8}, {"Omega", 0x03A9}, {"alpha", 0x03B1},
{"beta", 0x03B2}, {"gamma", 0x03B3}, {"delta", 0x03B4},
{"epsilon", 0x03B5}, {"zeta", 0x03B6}, {"eta", 0x03B7},
{"theta", 0x03B8}, {"iota", 0x03B9}, {"kappa", 0x03BA},
{"lambda", 0x03BB}, {"mu", 0x03BC}, {"nu", 0x03BD},
{"xi", 0x03BE}, {"omicron", 0x03BF}, {"pi", 0x03C0},
{"rho", 0x03C1}, {"sigmaf", 0x03C2}, {"sigma", 0x03C3},
{"tau", 0x03C4}, {"upsilon", 0x03C5}, {"phi", 0x03C6},
{"chi", 0x03C7}, {"psi", 0x03C8}, {"omega", 0x03C9},
{"thetasym", 0x03D1}, {"upsih", 0x03D2}, {"piv", 0x03D6},
{"ensp", 0x2002}, {"emsp", 0x2003}, {"thinsp", 0x2009},
{"zwnj", 0x200C}, {"zwj", 0x200D}, {"lrm", 0x200E},
{"rlm", 0x200F}, {"ndash", 0x2013}, {"mdash", 0x2014},
{"horbar", 0x2015}, {"lsquo", 0x2018}, {"rsquo", 0x2019},
{"sbquo", 0x201A}, {"ldquo", 0x201C}, {"rdquo", 0x201D},
{"bdquo", 0x201E}, {"dagger", 0x2020}, {"Dagger", 0x2021},
{"bull", 0x2022}, {"hellip", 0x2026}, {"permil", 0x2030},
{"prime", 0x2032}, {"Prime", 0x2033}, {"lsaquo", 0x2039},
{"rsaquo", 0x203A}, {"oline", 0x203E}, {"frasl", 0x2044},
{"euro", 0x20AC}, {"image", 0x2111}, {"weierp", 0x2118},
{"real", 0x211C}, {"trade", 0x2122}, {"alefsym", 0x2135},
{"larr", 0x2190}, {"uarr", 0x2191}, {"rarr", 0x2192},
{"darr", 0x2193}, {"harr", 0x2194}, {"crarr", 0x21B5},
{"lArr", 0x21D0}, {"uArr", 0x21D1}, {"rArr", 0x21D2},
{"dArr", 0x21D3}, {"hArr", 0x21D4}, {"forall", 0x2200},
{"part", 0x2202}, {"exist", 0x2203}, {"empty", 0x2205},
{"nabla", 0x2207}, {"isin", 0x2208}, {"notin", 0x2209},
{"ni", 0x220B}, {"prod", 0x220F}, {"sum", 0x2211},
{"minus", 0x2212}, {"lowast", 0x2217}, {"radic", 0x221A},
{"prop", 0x221D}, {"infin", 0x221E}, {"ang", 0x2220},
{"and", 0x2227}, {"or", 0x2228}, {"cap", 0x2229},
{"cup", 0x222A}, {"int", 0x222B}, {"there4", 0x2234},
{"sim", 0x223C}, {"cong", 0x2245}, {"asymp", 0x2248},
{"ne", 0x2260}, {"equiv", 0x2261}, {"le", 0x2264},
{"ge", 0x2265}, {"sub", 0x2282}, {"sup", 0x2283},
{"nsub", 0x2284}, {"sube", 0x2286}, {"supe", 0x2287},
{"oplus", 0x2295}, {"otimes", 0x2297}, {"perp", 0x22A5},
{"sdot", 0x22C5}, {"lceil", 0x2308}, {"rceil", 0x2309},
{"lfloor", 0x230A}, {"rfloor", 0x230B}, {"lang", 0x2329},
{"rang", 0x232A}, {"loz", 0x25CA}, {"spades", 0x2660},
{"clubs", 0x2663}, {"hearts", 0x2665}, {"diams", 0x2666}};
// Used to convert number to utf-8 char.
wstring_convert<codecvt_utf8<char32_t>, char32_t> u8c;
// Matches numbered entities between 1 and 8 digits, decimal or hexadecimal,
// or named entities.
const regex re_entity{"&(#(x)?([[:alnum:]]{1,8})"
"|[^;[:space:][:punct:]]+);"};
"|[^;[:space:][:punct:]]+);"};
smatch match;
while (regex_search(buffer, match, re_entity))
@ -189,8 +144,10 @@ string unescape_html(string html)
output += match.prefix().str();
try
{
// clang-format off
const char32_t codepoint{[&match, &names]
{
// clang-format on
// If it doesn't start with a '#' it is a named entity.
if (match[1].str()[0] != '#')
{
@ -199,12 +156,12 @@ string unescape_html(string html)
// 'x' after '#' means the number is hexadecimal.
if (match[2].length() == 1)
{
return static_cast<char32_t>(stoul(match[3].str(),
nullptr, 16));
return static_cast<char32_t>(
stoul(match[3].str(), nullptr, 16));
}
// '#' without 'x' means the number is decimal.
return static_cast<char32_t>(stoul(match[3].str(),
nullptr, 10));
return static_cast<char32_t>(
stoul(match[3].str(), nullptr, 10));
}()};
output += u8c.to_bytes(codepoint);
}

View File

@ -15,6 +15,7 @@
*/
#include "instance.hpp"
#include "log.hpp"
#include <algorithm>
@ -24,12 +25,12 @@
namespace mastodonpp
{
using std::sort;
using std::stoull;
using std::exception;
using std::regex;
using std::regex_search;
using std::smatch;
using std::sort;
using std::stoull;
Instance::Instance(const string_view hostname, const string_view access_token)
: _hostname{hostname}
@ -50,8 +51,8 @@ Instance::Instance(const Instance &other)
, _cainfo{other._cainfo}
, _useragent{other._useragent}
{
CURLWrapper::setup_connection_properties(_proxy, _access_token,
_cainfo, _useragent);
CURLWrapper::setup_connection_properties(_proxy, _access_token, _cainfo,
_useragent);
}
uint64_t Instance::get_max_chars() noexcept
@ -66,16 +67,18 @@ uint64_t Instance::get_max_chars() noexcept
try
{
debuglog << "Querying " << _hostname << " for max_toot_chars…\n";
const auto answer{make_request(http_method::GET,
_baseuri + "/api/v1/instance", {})};
const auto answer{
make_request(http_method::GET, _baseuri + "/api/v1/instance", {})};
if (!answer)
{
debuglog << "Could not get instance info.\n";
return default_max_chars;
}
// clang-format off
_max_chars = [&answer]
{
// clang-format on
const regex re_chars{R"("max_toot_chars"\s*:\s*([^"]+))"};
smatch match;
@ -100,8 +103,8 @@ uint64_t Instance::get_max_chars() noexcept
answer_type Instance::get_nodeinfo()
{
auto answer{make_request(http_method::GET,
_baseuri + "/.well-known/nodeinfo", {})};
auto answer{
make_request(http_method::GET, _baseuri + "/.well-known/nodeinfo", {})};
if (!answer)
{
debuglog << "NodeInfo not found.\n";
@ -177,11 +180,8 @@ answer_type Instance::ObtainToken::step_1(const string_view client_name,
const string_view scopes,
const string_view website)
{
parametermap parameters
{
{"client_name", client_name},
{"redirect_uris", "urn:ietf:wg:oauth:2.0:oob"}
};
parametermap parameters{{"client_name", client_name},
{"redirect_uris", "urn:ietf:wg:oauth:2.0:oob"}};
if (!scopes.empty())
{
_scopes = scopes;
@ -192,8 +192,8 @@ answer_type Instance::ObtainToken::step_1(const string_view client_name,
parameters.insert({"website", website});
}
auto answer{make_request(http_method::POST, _baseuri + "/api/v1/apps",
parameters)};
auto answer{
make_request(http_method::POST, _baseuri + "/api/v1/apps", parameters)};
if (answer)
{
const regex re_id{R"("client_id"\s*:\s*"([^"]+)\")"};
@ -210,9 +210,10 @@ answer_type Instance::ObtainToken::step_1(const string_view client_name,
}
string uri{_baseuri + "/oauth/authorize?scope=" + escape_url(scopes)
+ "&response_type=code"
"&redirect_uri=" + escape_url("urn:ietf:wg:oauth:2.0:oob")
+ "&client_id=" + _client_id};
+ "&response_type=code"
"&redirect_uri="
+ escape_url("urn:ietf:wg:oauth:2.0:oob")
+ "&client_id=" + _client_id};
if (!website.empty())
{
uri += "&website=" + escape_url(website);
@ -236,8 +237,8 @@ answer_type Instance::ObtainToken::step_2(const string_view code)
parameters.insert({"scope", _scopes});
}
auto answer{make_request(http_method::POST, _baseuri + "/oauth/token",
parameters)};
auto answer{
make_request(http_method::POST, _baseuri + "/oauth/token", parameters)};
if (answer)
{
const regex re_token{R"("access_token"\s*:\s*"([^"]+)\")"};

View File

@ -23,7 +23,7 @@
namespace mastodonpp
{
using std::cerr; // NOLINT(misc-unused-using-decls)
using std::cerr; // NOLINT(misc-unused-using-decls)
using std::string_view;
//! @private
@ -41,17 +41,17 @@ constexpr auto shorten_filename(const string_view &filename)
}
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define commonlog cerr << '[' << shorten_filename(__FILE__) \
<< ':' << __LINE__ << ']'
#define commonlog \
cerr << '[' << shorten_filename(__FILE__) << ':' << __LINE__ << ']'
#ifndef NDEBUG
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define debuglog commonlog << " DEBUG: "
# define debuglog commonlog << " DEBUG: "
#else
#define debuglog false && cerr
# define debuglog false && cerr
#endif
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define errorlog commonlog << " ERROR: "
} // namespace mastodonpp
#endif // MASTODONPP_LOG_HPP
#endif // MASTODONPP_LOG_HPP

View File

@ -1,5 +1,5 @@
/* This file is part of mastodonpp.
* Copyright © 2020 tastytea <tastytea@tastytea.de>
* Copyright © 2020, 2021 tastytea <tastytea@tastytea.de>
*
* 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
@ -14,9 +14,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "log.hpp"
#include "types.hpp"
#include "log.hpp"
#include <algorithm>
#include <cctype>
@ -36,7 +37,7 @@ answer_type::operator string_view() const
return body;
}
std::ostream &operator <<(std::ostream &out, const answer_type &answer)
std::ostream &operator<<(std::ostream &out, const answer_type &answer)
{
out << answer.body;
return out;
@ -45,10 +46,11 @@ std::ostream &operator <<(std::ostream &out, const answer_type &answer)
string_view answer_type::get_header(const string_view field) const
{
const string_view searchstring{string(field) += ':'};
auto it{search(headers.begin(), headers.end(),
searchstring.begin(), searchstring.end(),
[](unsigned char a, unsigned char b)
// clang-format off
auto it{search(headers.begin(), headers.end(), searchstring.begin(),
searchstring.end(), [](unsigned char a, unsigned char b)
{ return tolower(a) == tolower(b); })};
// clang-format on
if (it != headers.end())
{
@ -69,7 +71,7 @@ parametermap answer_type::parse_pagination(const bool next) const
return {};
}
const auto direction{next ? R"(rel="next")" : R"(rel="prev")"};
const string_view direction{next ? R"(rel="next")" : R"(rel="prev")"};
auto endpos{link.find(direction)};
endpos = link.rfind('>', endpos);
auto startpos{link.rfind('?', endpos) + 1};

View File

@ -3,11 +3,16 @@ include(CTest)
file(GLOB sources_tests test_*.cpp)
find_package(Catch2 CONFIG)
if(Catch2_FOUND) # Catch 2.x
if(Catch2_FOUND) # Catch 2.x / 3.x
include(Catch)
add_executable(all_tests main.cpp ${sources_tests})
target_link_libraries(all_tests
PRIVATE Catch2::Catch2 ${PROJECT_NAME})
if(TARGET Catch2::Catch2WithMain) # Catch 3.x
target_link_libraries(all_tests
PRIVATE Catch2::Catch2WithMain ${PROJECT_NAME})
else() # Catch 2.x
target_link_libraries(all_tests
PRIVATE Catch2::Catch2 ${PROJECT_NAME})
endif()
target_include_directories(all_tests PRIVATE "/usr/include/catch2")
catch_discover_tests(all_tests EXTRA_ARGS "${EXTRA_TEST_ARGS}")
else() # Catch 1.x

View File

@ -1,5 +1,5 @@
/* This file is part of mastodonpp.
* Copyright © 2020 tastytea <tastytea@tastytea.de>
* Copyright © 2020, 2022 tastytea <tastytea@tastytea.de>
*
* 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
@ -16,4 +16,9 @@
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
// catch 3 does not have catch.hpp anymore
#if __has_include(<catch.hpp>)
# include <catch.hpp>
#else
# include <catch_all.hpp>
#endif

View File

@ -1,5 +1,5 @@
/* This file is part of mastodonpp.
* Copyright © 2020 tastytea <tastytea@tastytea.de>
* Copyright © 2020, 2022 tastytea <tastytea@tastytea.de>
*
* 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
@ -14,22 +14,26 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "instance.hpp"
#include "connection.hpp"
#include "instance.hpp"
#include <catch.hpp>
// catch 3 does not have catch.hpp anymore
#if __has_include(<catch.hpp>)
# include <catch.hpp>
#else
# include <catch_all.hpp>
#endif
#include <exception>
namespace mastodonpp
{
SCENARIO ("mastodonpp::Connection.")
SCENARIO("mastodonpp::Connection.")
{
bool exception = false;
WHEN ("Connection is instantiated.")
WHEN("Connection is instantiated.")
{
try
{
@ -41,7 +45,7 @@ SCENARIO ("mastodonpp::Connection.")
exception = true;
}
THEN ("No exception is thrown")
THEN("No exception is thrown")
{
REQUIRE_FALSE(exception);
}

View File

@ -1,5 +1,5 @@
/* This file is part of mastodonpp.
* Copyright © 2020 tastytea <tastytea@tastytea.de>
* Copyright © 2020, 2022 tastytea <tastytea@tastytea.de>
*
* 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
@ -16,7 +16,12 @@
#include "helpers.hpp"
#include <catch.hpp>
// catch 3 does not have catch.hpp anymore
#if __has_include(<catch.hpp>)
# include <catch.hpp>
#else
# include <catch_all.hpp>
#endif
#include <exception>
#include <string>
@ -26,11 +31,11 @@ namespace mastodonpp
using std::string;
SCENARIO ("mastodonpp::html_unescape()")
SCENARIO("mastodonpp::html_unescape()")
{
bool exception = false;
WHEN ("html_unescape() is called.")
WHEN("html_unescape() is called.")
{
string result;
try
@ -42,8 +47,8 @@ SCENARIO ("mastodonpp::html_unescape()")
exception = true;
}
THEN ("No exception is thrown")
AND_THEN("Result is as expected.")
THEN("No exception is thrown")
AND_THEN("Result is as expected.")
{
REQUIRE_FALSE(exception);
REQUIRE(result == "2€ = 2€ = 2€");

View File

@ -1,5 +1,5 @@
/* This file is part of mastodonpp.
* Copyright © 2020 tastytea <tastytea@tastytea.de>
* Copyright © 2020, 2022 tastytea <tastytea@tastytea.de>
*
* 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
@ -16,7 +16,12 @@
#include "instance.hpp"
#include <catch.hpp>
// catch 3 does not have catch.hpp anymore
#if __has_include(<catch.hpp>)
# include <catch.hpp>
#else
# include <catch_all.hpp>
#endif
#include <exception>
#include <string>
@ -26,11 +31,11 @@ namespace mastodonpp
using std::string;
SCENARIO ("mastopp::Instance")
SCENARIO("mastopp::Instance")
{
bool exception = false;
WHEN ("Instance is instantiated.")
WHEN("Instance is instantiated.")
{
try
{
@ -41,13 +46,13 @@ SCENARIO ("mastopp::Instance")
exception = true;
}
THEN ("No exception is thrown")
THEN("No exception is thrown")
{
REQUIRE_FALSE(exception);
}
}
WHEN ("Variables are set.")
WHEN("Variables are set.")
{
constexpr auto hostname{"likeable.space"};
constexpr auto proxy{"socks4a://[::1]:9050"};
@ -64,10 +69,10 @@ SCENARIO ("mastopp::Instance")
exception = true;
}
THEN ("No exception is thrown")
AND_THEN ("get_access_token() returns the set value.")
AND_THEN ("get_hostname() returns the set value.")
AND_THEN ("get_baseuri() returns the expected value.")
THEN("No exception is thrown")
AND_THEN("get_access_token() returns the set value.")
AND_THEN("get_hostname() returns the set value.")
AND_THEN("get_baseuri() returns the expected value.")
{
REQUIRE_FALSE(exception);
REQUIRE(instance.get_access_token() == access_token);