Switch to C++17.

Update dependencies.
Rewrite tests to use Catch2 library.
Add CMake option to use LLVM libc++.
Delete bootstrap theme for Doxygen.
This commit is contained in:
Kirill Kirilenko 2020-11-29 21:39:44 +03:00
parent ad2290eca5
commit 0c71edab8b
46 changed files with 3057 additions and 3072 deletions

13
.gitignore vendored
View file

@ -1,9 +1,4 @@
build .idea
build-tests build*
cmake_install.cmake cmake-build-*
CMakeCache.txt tests/config.json
CMakeFiles
doc/html
lib
Makefile
tests/telebotxx-test

3
.gitmodules vendored
View file

@ -4,3 +4,6 @@
[submodule "ext/rapidjson"] [submodule "ext/rapidjson"]
path = ext/rapidjson path = ext/rapidjson
url = https://github.com/miloyip/rapidjson.git url = https://github.com/miloyip/rapidjson.git
[submodule "ext/Catch2"]
path = ext/Catch2
url = https://github.com/catchorg/Catch2.git

View file

@ -1,40 +1,30 @@
sudo: required sudo: required
dist: trusty dist: bionic
language: cpp language: cpp
matrix: matrix:
include: include:
- compiler: gcc - compiler: gcc
addons: env: COMPILER=g++
apt:
sources:
- sourceline: 'ppa:kzemek/boost'
- ubuntu-toolchain-r-test
packages:
- g++-4.9
env: COMPILER=g++-4.9
- compiler: clang - compiler: clang
addons: env: COMPILER=clang++
apt:
sources:
- sourceline: 'ppa:kzemek/boost'
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.6
packages:
- clang-3.6
env: COMPILER=clang++-3.6
env: install:
global: # Install CMake 3.15.0
- TELEBOTXX_BUILD_TESTS=ON - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- TELEBOTXX_GENERATE_DOC=OFF - mkdir ${DEPS_DIR} && cd ${DEPS_DIR}
- travis_retry wget --no-check-certificate https://cmake.org/files/v3.15/cmake-3.15.0-Linux-x86_64.tar.gz
- tar -xvf cmake-3.15.0-Linux-x86_64.tar.gz > /dev/null
- mv cmake-3.15.0-Linux-x86_64 cmake-install
- PATH=${DEPS_DIR}/cmake-install:${DEPS_DIR}/cmake-install/bin:${PATH}
- cd ${TRAVIS_BUILD_DIR}
before_script: before_script:
- sudo apt-get install -y libboost1.58-dev libboost-test1.58-dev libboost-system1.58-dev libcurl4-openssl-dev - sudo apt-get install -y libcurl4-openssl-dev
- export CXX=$COMPILER - export CXX=$COMPILER
- mkdir build - mkdir build
- cd build - cd build
- cmake .. - cmake -DCMAKE_BUILD_TYPE=Release -DTELEBOTXX_BUILD_TESTS=ON -DTELEBOTXX_GENERATE_DOC=OFF ..
script: script:
- make VERBOSE=1 - cmake --build .

View file

@ -1,53 +1,46 @@
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 3.15)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} cmake) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} cmake)
if (NOT DEFINED CMAKE_BUILD_TYPE) if (NOT DEFINED CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Type of build (Release, Debug, RelWithDebInfo, MinSizeRel)") set(CMAKE_BUILD_TYPE Release)
endif() endif()
project(telebotxx CXX) project(telebotxx CXX)
option (TELEBOTXX_BUILD_TESTS "Build unit tests using Boost.Test" ON) option(TELEBOTXX_USE_LIBCXX "Use LLVM libc++ as C++ standard library" OFF)
option (TELEBOTXX_GENERATE_DOC "Generate API documentation with Doxygen" ON) option(TELEBOTXX_BUILD_TESTS "Build unit tests using Boost.Test" OFF)
option(TELEBOTXX_GENERATE_DOC "Generate API documentation with Doxygen" OFF)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
if (TELEBOTXX_USE_LIBCXX)
if (UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
link_libraries(c++abi)
endif()
if(MSVC)
# TODO
message(WARNING "libc++ with MSVC is not yet supported")
endif()
endif()
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin") set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin")
set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/lib") set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/lib")
# Build and include Curl for People # Build dependencies
set(BUILD_CPR_TESTS OFF CACHE BOOL "Do not build cpr tests") add_subdirectory(ext)
find_package(CURL)
if(CURL_FOUND)
set(USE_SYSTEM_CURL ON CACHE BOOL "Use the system curl for faster builds")
endif()
add_subdirectory(${PROJECT_SOURCE_DIR}/ext/cpr)
include_directories(${CPR_INCLUDE_DIRS})
# Include RapidJSON headers
include_directories(${PROJECT_SOURCE_DIR}/ext/rapidjson/include)
# Build library # Build library
include_directories(include)
add_subdirectory(src) add_subdirectory(src)
# Build tests # Build tests
if(TELEBOTXX_BUILD_TESTS) if(TELEBOTXX_BUILD_TESTS)
add_subdirectory(tests) add_subdirectory(tests)
endif(TELEBOTXX_BUILD_TESTS) endif()
# Generate docs # Generate docs
if(TELEBOTXX_GENERATE_DOC) if(TELEBOTXX_GENERATE_DOC)
find_package(Doxygen) add_subdirectory(doc)
if(DOXYGEN_FOUND) endif()
configure_file(${PROJECT_SOURCE_DIR}/Doxyfile.in Doxyfile)
# Bootstrap theme for Doxygen
file(COPY ${PROJECT_SOURCE_DIR}/doc/bootstrap.min.js
${PROJECT_SOURCE_DIR}/doc/bootstrap.min.css
${PROJECT_SOURCE_DIR}/doc/doxy-boot.js
DESTINATION doc/html)
add_custom_target(telebotxx-doc ALL COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile COMMENT "Generating API documentation with Doxygen")
else(DOXYGEN_FOUND)
message(STATUS "WARNING: Doxygen not found - Reference manual will not be created")
endif(DOXYGEN_FOUND)
endif(TELEBOTXX_GENERATE_DOC)

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,12 @@
# telebotxx # telebotxx
[![Build Status](https://travis-ci.org/UltraCoderRU/telebotxx.svg?branch=master)](https://travis-ci.org/UltraCoderRU/telebotxx) [![Build Status](https://travis-ci.org/UltraCoderRU/telebotxx.svg?branch=master)](https://travis-ci.org/UltraCoderRU/telebotxx)
Telegram Bot API 2.0 for C++14. It uses [C++ Requests](https://github.com/whoshuu/cpr) library to perform HTTP requests and [RapidJSON](https://github.com/miloyip/rapidjson) to work with JSON data. Telegram Bot API 2.0 for C++17. It uses [C++ Requests](https://github.com/whoshuu/cpr) library to perform HTTP requests and [RapidJSON](https://github.com/miloyip/rapidjson) to work with JSON data.
In development, so you are welcome to contribute. In development, so you are welcome to contribute.
## Requirements ## Requirements
* C++14-compatible compiler * C++17-compatible compiler
* CMake 2.8 or newer * CMake 3.15 or newer
* Boost 1.54+
* Boost Unit Test Framework (only for tests)
## Building ## Building
*You can set available options in CMakeLists.txt before running configure script.* *You can set available options in CMakeLists.txt before running configure script.*
@ -16,8 +14,8 @@ In development, so you are welcome to contribute.
git submodule update --init --recursive git submodule update --init --recursive
mkdir build mkdir build
cd build cd build
cmake .. cmake -DCMAKE_BUILD_TYPE=Release ..
make cmake --build .
``` ```
## Usage ## Usage

View file

@ -1,26 +0,0 @@
cmake_minimum_required(VERSION 2.8)
function(RequireCXX14)
message(STATUS "Checking compiler flags for C++14 support.")
# Set C++14 support flags for various compilers
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-std=c++14" COMPILER_SUPPORTS_CXX14)
check_cxx_compiler_flag("-std=c++1y" COMPILER_SUPPORTS_CXX1Y)
if(COMPILER_SUPPORTS_CXX14)
message(STATUS "C++14 is supported.")
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -stdlib=libc++" PARENT_SCOPE)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14" PARENT_SCOPE)
endif()
elseif(COMPILER_SUPPORTS_CXX1Y)
message(STATUS "C++1y is supported.")
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -stdlib=libc++" PARENT_SCOPE)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y" PARENT_SCOPE)
endif()
else()
message(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support. Please use a different C++ compiler.")
endif()
endfunction()

10
doc/CMakeLists.txt Normal file
View file

@ -0,0 +1,10 @@
find_package(Doxygen)
if(DOXYGEN_FOUND)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
add_custom_target(telebotxx-doc ALL COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen")
else()
message(STATUS "WARNING: Doxygen not found - Reference manual will not be created")
endif()

2533
doc/Doxyfile.in Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,320 +0,0 @@
h1, .h1, h2, .h2, h3, .h3{
font-weight: 200 !important;
}
#navrow1, #navrow2, #navrow3, #navrow4, #navrow5{
border-bottom: 1px solid #EEEEEE;
}
.adjust-right {
margin-left: 30px !important;
font-size: 1.15em !important;
}
.navbar{
border: 0px solid #222 !important;
margin-bottom: 0px !important;
}
/* Sticky footer styles
-------------------------------------------------- */
html,
body {
height: 100%;
/* The html and body elements cannot have any padding or margin. */
}
body, table, div, p, dl, a, ul, span, li, ol{
font-family: 'Open Sans', sans-serif !important;
}
/* Wrapper for page content to push down footer */
#wrap {
min-height: 100%;
height: auto;
/* Negative indent footer by its height */
margin: 0 auto -60px;
/* Pad bottom by footer height */
padding: 0 0 60px;
}
#top {
margin-top: 25px;
}
/* Set the fixed height of the footer here */
#footer {
font-size: 0.9em;
padding: 8px 0px;
background-color: #f5f5f5;
}
.footer-row {
line-height: 44px;
}
#footer > .container {
padding-left: 15px;
padding-right: 15px;
}
.footer-follow-icon {
margin-left: 3px;
text-decoration: none !important;
}
.footer-follow-icon img {
width: 20px;
}
.footer-link {
padding-top: 5px;
display: inline-block;
color: #999999;
text-decoration: none;
}
.footer-copyright {
text-align: center;
}
@media (min-width: 768px) and (max-width: 991px) {
.adjust-right {
margin: 0px -5px;
}
}
@media (min-width: 768px) {
.nav > li > a {
padding-left: 9px !important;
padding-right: 9px !important;
}
}
@media (min-width: 992px) {
.footer-row {
text-align: left;
}
.footer-icons {
text-align: right;
}
}
@media (max-width: 991px) {
.footer-row {
text-align: center;
}
.footer-icons {
text-align: center;
}
}
/* DOXYGEN Code Styles
----------------------------------- */
a.qindex {
font-weight: bold;
}
a.qindexHL {
font-weight: bold;
background-color: #9CAFD4;
color: #ffffff;
border: 1px double #869DCA;
}
.contents a.qindexHL:visited {
color: #ffffff;
}
a.code, a.code:visited, a.line, a.line:visited {
color: #4665A2;
}
a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
color: #4665A2;
}
/* @end */
dl.el {
margin-left: -1cm;
}
pre.fragment {
border: 1px solid #C4CFE5;
background-color: #FBFCFD;
padding: 4px 6px;
margin: 4px 8px 4px 2px;
overflow: auto;
word-wrap: break-word;
font-size: 9pt;
line-height: 125%;
font-family: monospace, fixed;
font-size: 105%;
}
div.fragment {
padding: 4px 6px;
margin: 4px 8px 4px 2px;
border: 1px solid #C4CFE5;
}
div.line {
font-family: monospace, fixed;
font-size: 13px;
min-height: 13px;
line-height: 1.0;
text-wrap: unrestricted;
white-space: -moz-pre-wrap; /* Moz */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
white-space: pre-wrap; /* CSS3 */
word-wrap: break-word; /* IE 5.5+ */
text-indent: -53px;
padding-left: 53px;
padding-bottom: 0px;
margin: 0px;
-webkit-transition-property: background-color, box-shadow;
-webkit-transition-duration: 0.5s;
-moz-transition-property: background-color, box-shadow;
-moz-transition-duration: 0.5s;
-ms-transition-property: background-color, box-shadow;
-ms-transition-duration: 0.5s;
-o-transition-property: background-color, box-shadow;
-o-transition-duration: 0.5s;
transition-property: background-color, box-shadow;
transition-duration: 0.5s;
}
div.line.glow {
background-color: cyan;
box-shadow: 0 0 10px cyan;
}
span.lineno {
padding-right: 4px;
text-align: right;
border-right: 2px solid #0F0;
background-color: #E8E8E8;
white-space: pre;
}
span.lineno a {
background-color: #D8D8D8;
}
span.lineno a:hover {
background-color: #C8C8C8;
}
div.groupHeader {
margin-left: 16px;
margin-top: 12px;
font-weight: bold;
}
div.groupText {
margin-left: 16px;
font-style: italic;
}
/* @group Code Colorization */
span.keyword {
color: #008000
}
span.keywordtype {
color: #604020
}
span.keywordflow {
color: #e08000
}
span.comment {
color: #800000
}
span.preprocessor {
color: #806020
}
span.stringliteral {
color: #002080
}
span.charliteral {
color: #008080
}
span.vhdldigit {
color: #ff00ff
}
span.vhdlchar {
color: #000000
}
span.vhdlkeyword {
color: #700070
}
span.vhdllogic {
color: #ff0000
}
blockquote {
background-color: #F7F8FB;
border-left: 2px solid #9CAFD4;
margin: 0 24px 0 4px;
padding: 0 12px 0 16px;
}
/* Google Custom Search Engine Tweaks START */
input.gsc-input,
.gsc-input-box,
.gsc-input-box-hover,
.gsc-input-box-focus,
.gsc-search-button {
box-sizing: content-box;
line-height: normal;
}
.gsc-table-result,
.gsc-thumbnail-inside,
.gsc-url-top {
padding-left: 0px !important;
}
.gsc-selected-option-container {
width: inherit !important;
}
.reset-box-sizing,
.reset-box-sizing * {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
@media (min-width: 768px) {
.google-cse {
top: 50px;
}
}
@media (max-width: 767px) {
.google-cse {
top: 391px;
}
}
.google-cse {
width: 100%;
left: 0px;
z-index: 9999;
background-color: #222;
}
/* Google Custom Search Engine Tweaks END */

View file

@ -1,120 +0,0 @@
$( document ).ready(function() {
$("div.headertitle").addClass("page-header");
$("div.title").addClass("h1");
$('li > a[href="index.html"] > span').before("<i class='fa fa-cog'></i> ");
$('li > a[href="modules.html"] > span').before("<i class='fa fa-square'></i> ");
$('li > a[href="namespaces.html"] > span').before("<i class='fa fa-bars'></i> ");
$('li > a[href="annotated.html"] > span').before("<i class='fa fa-list-ul'></i> ");
$('li > a[href="classes.html"] > span').before("<i class='fa fa-book'></i> ");
$('li > a[href="inherits.html"] > span').before("<i class='fa fa-sitemap'></i> ");
$('li > a[href="functions.html"] > span').before("<i class='fa fa-list'></i> ");
$('li > a[href="functions_func.html"] > span').before("<i class='fa fa-list'></i> ");
$('li > a[href="functions_vars.html"] > span').before("<i class='fa fa-list'></i> ");
$('li > a[href="functions_enum.html"] > span').before("<i class='fa fa-list'></i> ");
$('li > a[href="functions_eval.html"] > span').before("<i class='fa fa-list'></i> ");
$('img[src="ftv2ns.png"]').replaceWith('<span class="label label-danger">N</span> ');
$('img[src="ftv2cl.png"]').replaceWith('<span class="label label-danger">C</span> ');
$("ul.tablist").addClass("nav nav-pills nav-justified");
$("ul.tablist").css("margin-top", "0.5em");
$("ul.tablist").css("margin-bottom", "0.5em");
$("li.current").addClass("active");
$("iframe").attr("scrolling", "yes");
$("#nav-path > ul").addClass("breadcrumb");
$("table.params").addClass("table");
$("div.ingroups").wrapInner("<small></small>");
$("div.levels").css("margin", "0.5em");
$("div.levels > span").addClass("btn btn-default btn-xs");
$("div.levels > span").css("margin-right", "0.25em");
$("table.directory").addClass("table table-striped");
$("div.summary > a").addClass("btn btn-default btn-xs");
$("table.fieldtable").addClass("table");
$(".fragment").addClass("well");
$(".memitem").addClass("panel panel-default");
$(".memproto").addClass("panel-heading");
$(".memdoc").addClass("panel-body");
$("span.mlabel").addClass("label label-info");
$("table.memberdecls").addClass("table");
$("[class^=memitem]").addClass("active");
$("div.ah").addClass("btn btn-default");
$("span.mlabels").addClass("pull-right");
$("table.mlabels").css("width", "100%")
$("td.mlabels-right").addClass("pull-right");
$("div.ttc").addClass("panel panel-primary");
$("div.ttname").addClass("panel-heading");
$("div.ttname a").css("color", 'white');
$("div.ttdef,div.ttdoc,div.ttdeci").addClass("panel-body");
$('#MSearchBox').parent().remove();
$('div.fragment.well div.line:first').css('margin-top', '15px');
$('div.fragment.well div.line:last').css('margin-bottom', '15px');
$('table.doxtable').removeClass('doxtable').addClass('table table-striped table-bordered').each(function(){
$(this).prepend('<thead></thead>');
$(this).find('tbody > tr:first').prependTo($(this).find('thead'));
$(this).find('td > span.success').parent().addClass('success');
$(this).find('td > span.warning').parent().addClass('warning');
$(this).find('td > span.danger').parent().addClass('danger');
});
if($('div.fragment.well div.ttc').length > 0)
{
$('div.fragment.well div.line:first').parent().removeClass('fragment well');
}
$('table.memberdecls').find('.memItemRight').each(function(){
$(this).contents().appendTo($(this).siblings('.memItemLeft'));
$(this).siblings('.memItemLeft').attr('align', 'left');
});
function getOriginalWidthOfImg(img_element) {
var t = new Image();
t.src = (img_element.getAttribute ? img_element.getAttribute("src") : false) || img_element.src;
return t.width;
}
$('div.dyncontent').find('img').each(function(){
if(getOriginalWidthOfImg($(this)[0]) > $('#content>div.container').width())
$(this).css('width', '100%');
});
$(".memitem").removeClass('memitem');
$(".memproto").removeClass('memproto');
$(".memdoc").removeClass('memdoc');
$("span.mlabel").removeClass('mlabel');
$("table.memberdecls").removeClass('memberdecls');
$("[class^=memitem]").removeClass('memitem');
$("span.mlabels").removeClass('mlabels');
$("table.mlabels").removeClass('mlabels');
$("td.mlabels-right").removeClass('mlabels-right');
$(".navpath").removeClass('navpath');
$("li.navelem").removeClass('navelem');
$("a.el").removeClass('el');
$("div.ah").removeClass('ah');
$("div.header").removeClass("header");
$('.mdescLeft').each(function(){
if($(this).html()=="&nbsp;") {
$(this).siblings('.mdescRight').attr('colspan', 2);
$(this).remove();
}
});
$('td.memItemLeft').each(function(){
if($(this).siblings('.memItemRight').html()=="") {
$(this).attr('colspan', 2);
$(this).siblings('.memItemRight').remove();
}
});
});

View file

@ -1,26 +0,0 @@
<!-- HTML footer for doxygen 1.8.8-->
<!-- start footer part -->
<!--BEGIN GENERATE_TREEVIEW-->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
$navpath
<li class="footer">$generatedby
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
</ul>
</div>
<!--END GENERATE_TREEVIEW-->
</div>
</div>
</div>
</div>
</div>
<!--BEGIN !GENERATE_TREEVIEW-->
<hr class="footer"/><address class="footer"><small>
$generatedby &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
</a> $doxygenversion
</small></address>
<!--END !GENERATE_TREEVIEW-->
</body>
</html>

View file

@ -1,44 +0,0 @@
<!-- HTML header for doxygen 1.8.8-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- For Mobile Devices -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen $doxygenversion"/>
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,700&subset=latin,cyrillic' rel='stylesheet' type='text/css'>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
<!--<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>-->
<script type="text/javascript" src="$relpath^dynsections.js"></script>
$treeview
$search
$mathjax
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
$extrastylesheet
<link href="bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="bootstrap.min.js"></script>
<script type="text/javascript" src="doxy-boot.js"></script>
</head>
<body>
<nav class="navbar navbar-default" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand">$projectname $projectnumber</a>
</div>
</div>
</nav>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div class="content" id="content">
<div class="container">
<div class="row">
<div class="col-sm-12 panel panel-default" style="padding-bottom: 15px;">
<div style="margin-bottom: 15px;">
<!-- end header part -->

6
ext/CMakeLists.txt Normal file
View file

@ -0,0 +1,6 @@
include(cpr.cmake)
include(rapidjson.cmake)
if (TELEBOTXX_BUILD_TESTS)
include(Catch2.cmake)
endif()

1
ext/Catch2 Submodule

@ -0,0 +1 @@
Subproject commit e7740316e37072131a4d6d9eeb56eabfd867dbf2

3
ext/Catch2.cmake Normal file
View file

@ -0,0 +1,3 @@
set(CATCH_INSTALL_DOCS OFF CACHE INTERNAL "")
set(CATCH_INSTALL_EXTRAS OFF CACHE INTERNAL "")
add_subdirectory(Catch2)

@ -1 +1 @@
Subproject commit 07d784ccfe6760fc6da47c24f7326e64d8e11460 Subproject commit 41fbaca90160950f1397e0ffc6b58bd81063f131

8
ext/cpr.cmake Normal file
View file

@ -0,0 +1,8 @@
# Build Curl for People
set(BUILD_CPR_TESTS OFF CACHE BOOL "Do not build cpr tests")
find_package(CURL)
if(CURL_FOUND)
set(USE_SYSTEM_CURL ON CACHE BOOL "Use the system curl for faster builds")
endif()
add_subdirectory(cpr)

@ -1 +1 @@
Subproject commit 418331e99f859f00bdc8306f69eba67e8693c55e Subproject commit 0ccdbf364c577803e2a751f5aededce935314313

2
ext/rapidjson.cmake Normal file
View file

@ -0,0 +1,2 @@
add_library(rapidjson INTERFACE IMPORTED GLOBAL)
target_include_directories(rapidjson INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/include)

View file

@ -1,12 +1,11 @@
#ifndef TELEBOTXX_ATTACHMENT_HPP #ifndef TELEBOTXX_ATTACHMENT_HPP
#define TELEBOTXX_ATTACHMENT_HPP #define TELEBOTXX_ATTACHMENT_HPP
#include "Optional.hpp"
#include <string> #include <string>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <boost/variant/variant.hpp> #include <variant>
#include <optional>
namespace telebotxx { namespace telebotxx {
@ -24,14 +23,14 @@ public:
int getHeight() const; int getHeight() const;
void setHeight(int height); void setHeight(int height);
const optional<int>& getFileSize() const; const std::optional<int>& getFileSize() const;
void setFileSize(optional<int> fileSize); void setFileSize(std::optional<int> fileSize);
private: private:
std::string fileId_; std::string fileId_;
int width_; int width_;
int height_; int height_;
optional<int> fileSize_; std::optional<int> fileSize_;
}; };
using PhotoSizeArray = std::vector<PhotoSize>; using PhotoSizeArray = std::vector<PhotoSize>;
@ -47,25 +46,25 @@ public:
int getDuration() const; int getDuration() const;
void setDuration(int duration); void setDuration(int duration);
const optional<std::string>& getPerformer() const; const std::optional<std::string>& getPerformer() const;
void setPerformer(optional<std::string> performer); void setPerformer(std::optional<std::string> performer);
const optional<std::string>& getTitle() const; const std::optional<std::string>& getTitle() const;
void setTitle(optional<std::string> title); void setTitle(std::optional<std::string> title);
const optional<std::string>& getMimeType() const; const std::optional<std::string>& getMimeType() const;
void setMimeType(optional<std::string> mimeType); void setMimeType(std::optional<std::string> mimeType);
const optional<int>& getFileSize() const; const std::optional<int>& getFileSize() const;
void setFileSize(optional<int> fileSize); void setFileSize(std::optional<int> fileSize);
private: private:
std::string fileId_; std::string fileId_;
int duration_; int duration_;
optional<std::string> performer_; std::optional<std::string> performer_;
optional<std::string> title_; std::optional<std::string> title_;
optional<std::string> mimeType_; std::optional<std::string> mimeType_;
optional<int> fileSize_; std::optional<int> fileSize_;
}; };
class Document class Document
@ -76,24 +75,24 @@ public:
const std::string& getFileId() const; const std::string& getFileId() const;
void setFileId(std::string fileId); void setFileId(std::string fileId);
const optional<PhotoSize>& getThumb() const; const std::optional<PhotoSize>& getThumb() const;
void setThumb(optional<PhotoSize> thumb); void setThumb(std::optional<PhotoSize> thumb);
const optional<std::string>& getFileName() const; const std::optional<std::string>& getFileName() const;
void setFileName(optional<std::string> fileName); void setFileName(std::optional<std::string> fileName);
const optional<std::string>& getMimeType() const; const std::optional<std::string>& getMimeType() const;
void setMimeType(optional<std::string> mimeType); void setMimeType(std::optional<std::string> mimeType);
const optional<int>& getFileSize() const; const std::optional<int>& getFileSize() const;
void setFileSize(optional<int> fileSize); void setFileSize(std::optional<int> fileSize);
private: private:
std::string fileId_; std::string fileId_;
optional<PhotoSize> thumb_; std::optional<PhotoSize> thumb_;
optional<std::string> fileName_; std::optional<std::string> fileName_;
optional<std::string> mimeType_; std::optional<std::string> mimeType_;
optional<int> fileSize_; std::optional<int> fileSize_;
}; };
class Sticker class Sticker
@ -110,22 +109,22 @@ public:
int getHeight() const; int getHeight() const;
void setHeight(int height); void setHeight(int height);
const optional<PhotoSize>& getThumb() const; const std::optional<PhotoSize>& getThumb() const;
void setThumb(optional<PhotoSize> thumb); void setThumb(std::optional<PhotoSize> thumb);
const optional<std::string>& getEmoji() const; const std::optional<std::string>& getEmoji() const;
void setEmoji(optional<std::string> emoji); void setEmoji(std::optional<std::string> emoji);
const optional<int>& getFileSize() const; const std::optional<int>& getFileSize() const;
void setFileSize(optional<int> fileSize); void setFileSize(std::optional<int> fileSize);
private: private:
std::string fileId_; std::string fileId_;
int width_; int width_;
int height_; int height_;
optional<PhotoSize> thumb_; std::optional<PhotoSize> thumb_;
optional<std::string> emoji_; std::optional<std::string> emoji_;
optional<int> fileSize_; std::optional<int> fileSize_;
}; };
class Attachment class Attachment
@ -159,7 +158,7 @@ public:
private: private:
Type type_; Type type_;
boost::variant<PhotoSizeArray, Audio, Document, Sticker> value_; std::variant<PhotoSizeArray, Audio, Document, Sticker> value_;
}; };
} }

View file

@ -85,7 +85,7 @@ public:
Updates getUpdates(int offset = 0, unsigned short limit = 0, unsigned timeout = 0); Updates getUpdates(int offset = 0, unsigned short limit = 0, unsigned timeout = 0);
private: private:
std::string getTelegramMainUrl() const; [[nodiscard]] std::string getTelegramMainUrl() const;
class Impl; class Impl;
std::unique_ptr<Impl> impl_; std::unique_ptr<Impl> impl_;

View file

@ -1,11 +1,10 @@
#ifndef TELEBOTXX_CHAT_HPP #ifndef TELEBOTXX_CHAT_HPP
#define TELEBOTXX_CHAT_HPP #define TELEBOTXX_CHAT_HPP
#include "Optional.hpp"
#include <string> #include <string>
#include <memory> #include <memory>
#include <cstdint> #include <cstdint>
#include <optional>
namespace telebotxx { namespace telebotxx {
@ -28,17 +27,17 @@ public:
Type getType() const; Type getType() const;
void setType(Type type); void setType(Type type);
const optional<std::string>& getTitle() const; const std::optional<std::string>& getTitle() const;
void setTitle(optional<std::string> title); void setTitle(std::optional<std::string> title);
const optional<std::string>& getUsername() const; const std::optional<std::string>& getUsername() const;
void setUsername(optional<std::string> username); void setUsername(std::optional<std::string> username);
const optional<std::string>& getFirstName() const; const std::optional<std::string>& getFirstName() const;
void setFirstName(optional<std::string> firstName); void setFirstName(std::optional<std::string> firstName);
const optional<std::string>& getLastName() const; const std::optional<std::string>& getLastName() const;
void setLastName(optional<std::string> lastName); void setLastName(std::optional<std::string> lastName);
bool isAllAdmins() const; bool isAllAdmins() const;
void setAllAdmins(bool allAdmins); void setAllAdmins(bool allAdmins);
@ -46,10 +45,10 @@ public:
private: private:
std::int64_t id_; std::int64_t id_;
Type type_; Type type_;
optional<std::string> title_; std::optional<std::string> title_;
optional<std::string> username_; std::optional<std::string> username_;
optional<std::string> firstName_; std::optional<std::string> firstName_;
optional<std::string> lastName_; std::optional<std::string> lastName_;
bool allAdmins_; bool allAdmins_;
}; };

View file

@ -4,12 +4,11 @@
#include "User.hpp" #include "User.hpp"
#include "Chat.hpp" #include "Chat.hpp"
#include "Attachment.hpp" #include "Attachment.hpp"
#include "Optional.hpp"
#include <vector> #include <vector>
#include <ctime> #include <ctime>
#include <memory> #include <memory>
#include <boost/variant/variant.hpp> #include <optional>
namespace telebotxx { namespace telebotxx {
@ -42,18 +41,18 @@ public:
size_t getLength() const; size_t getLength() const;
void setLength(size_t length); void setLength(size_t length);
const optional<std::string>& getUrl() const; const std::optional<std::string>& getUrl() const;
void setUrl(std::string url); void setUrl(std::string url);
const optional<User>& getUser() const; const std::optional<User>& getUser() const;
void setUser(User user); void setUser(User user);
private: private:
Type type_; Type type_;
int offset_; int offset_;
std::size_t length_; std::size_t length_;
optional<std::string> url_; std::optional<std::string> url_;
optional<User> user_; std::optional<User> user_;
}; };
MessageEntity::Type messageEntityTypeFromString(const std::string& str); MessageEntity::Type messageEntityTypeFromString(const std::string& str);
@ -71,8 +70,8 @@ public:
int getId() const; int getId() const;
void setId(int id); void setId(int id);
const optional<User>& getFrom() const; const std::optional<User>& getFrom() const;
void setFrom(optional<User> from); void setFrom(std::optional<User> from);
time_t getDate() const; time_t getDate() const;
void setDate(time_t date); void setDate(time_t date);
@ -80,44 +79,44 @@ public:
const Chat& getChat() const; const Chat& getChat() const;
void setChat(Chat chat); void setChat(Chat chat);
const optional<User>& getForwardFrom() const; const std::optional<User>& getForwardFrom() const;
void setForwardFrom(optional<User> forwardFrom); void setForwardFrom(std::optional<User> forwardFrom);
const optional<Chat>& getForwardFromChat() const; const std::optional<Chat>& getForwardFromChat() const;
void setForwardFromChat(optional<Chat> forwardFromChat); void setForwardFromChat(std::optional<Chat> forwardFromChat);
const optional<time_t>& getForwardDate() const; const std::optional<time_t>& getForwardDate() const;
void setForwardDate(optional<time_t> forwardDate); void setForwardDate(std::optional<time_t> forwardDate);
MessagePtr getReplyToMessage() const; MessagePtr getReplyToMessage() const;
void setReplyToMessage(MessagePtr replyToMessage); void setReplyToMessage(MessagePtr replyToMessage);
const optional<time_t>& getEditDate() const; const std::optional<time_t>& getEditDate() const;
void setEditDate(optional<time_t> editDate); void setEditDate(std::optional<time_t> editDate);
const optional<std::string>& getText() const; const std::optional<std::string>& getText() const;
void setText(optional<std::string> text); void setText(std::optional<std::string> text);
const optional<MessageEntities>& getEntities() const; const std::optional<MessageEntities>& getEntities() const;
void setEntities(optional<MessageEntities> entities); void setEntities(std::optional<MessageEntities> entities);
const optional<Attachment>& getAttachment() const; const std::optional<Attachment>& getAttachment() const;
void setAttachment(optional<Attachment> attachment); void setAttachment(std::optional<Attachment> attachment);
const optional<std::string>& getCaption() const; const std::optional<std::string>& getCaption() const;
void setCaption(optional<std::string> caption); void setCaption(std::optional<std::string> caption);
const optional<User>& getNewChatMember() const; const std::optional<User>& getNewChatMember() const;
void setNewChatMember(optional<User> newChatMember); void setNewChatMember(std::optional<User> newChatMember);
const optional<User>& getLeftChatMember() const; const std::optional<User>& getLeftChatMember() const;
void setLeftChatMember(optional<User> leftChatMember); void setLeftChatMember(std::optional<User> leftChatMember);
const optional<std::string>& getNewChatTitle() const; const std::optional<std::string>& getNewChatTitle() const;
void setNewChatTitle(optional<std::string> newChatTitle); void setNewChatTitle(std::optional<std::string> newChatTitle);
const optional<PhotoSizeArray> getNewChatPhoto() const; const std::optional<PhotoSizeArray> getNewChatPhoto() const;
void setNewChatPhoto(optional<PhotoSizeArray> newChatPhoto); void setNewChatPhoto(std::optional<PhotoSizeArray> newChatPhoto);
bool isDeleteChatPhoto() const; bool isDeleteChatPhoto() const;
void setDeleteChatPhoto(bool deleteChatPhoto); void setDeleteChatPhoto(bool deleteChatPhoto);
@ -131,40 +130,40 @@ public:
bool isChannelChatCreated() const; bool isChannelChatCreated() const;
void setChannelChatCreated(bool channelChatCreated); void setChannelChatCreated(bool channelChatCreated);
const optional<std::int64_t>& getMigrateToChatId() const; const std::optional<std::int64_t>& getMigrateToChatId() const;
void setMigrateToChatId(optional<std::int64_t> migrateToChatId); void setMigrateToChatId(std::optional<std::int64_t> migrateToChatId);
const optional<std::int64_t>& getMigrateFromChatId() const; const std::optional<std::int64_t>& getMigrateFromChatId() const;
void setMigrateFromChatId(optional<std::int64_t> migrateFromChatId); void setMigrateFromChatId(std::optional<std::int64_t> migrateFromChatId);
MessagePtr getPinnedMessage() const; MessagePtr getPinnedMessage() const;
void setPinnedMessage(MessagePtr pinnedMessage); void setPinnedMessage(MessagePtr pinnedMessage);
private: private:
int id_; int id_;
optional<User> from_; std::optional<User> from_;
std::time_t date_; std::time_t date_;
Chat chat_; Chat chat_;
optional<User> forwardFrom_; std::optional<User> forwardFrom_;
optional<Chat> forwardFromChat_; std::optional<Chat> forwardFromChat_;
optional<int> forwardFromMessageId_; std::optional<int> forwardFromMessageId_;
optional<std::time_t> forwardDate_; std::optional<std::time_t> forwardDate_;
MessagePtr replyToMessage_; MessagePtr replyToMessage_;
optional<std::time_t> editDate_; std::optional<std::time_t> editDate_;
optional<std::string> text_; std::optional<std::string> text_;
optional<MessageEntities> entities_; std::optional<MessageEntities> entities_;
optional<Attachment> attachment_; std::optional<Attachment> attachment_;
optional<std::string> caption_; std::optional<std::string> caption_;
optional<User> newChatMember_; std::optional<User> newChatMember_;
optional<User> leftChatMember_; std::optional<User> leftChatMember_;
optional<std::string> newChatTitle_; std::optional<std::string> newChatTitle_;
optional<PhotoSizeArray> newChatPhoto_; std::optional<PhotoSizeArray> newChatPhoto_;
bool deleteChatPhoto_; bool deleteChatPhoto_;
bool groupChatCreated_; bool groupChatCreated_;
bool superGroupChatCreated_; bool superGroupChatCreated_;
bool channelChatCreated_; bool channelChatCreated_;
optional<std::int64_t> migrateToChatId_; std::optional<std::int64_t> migrateToChatId_;
optional<std::int64_t> migrateFromChatId_; std::optional<std::int64_t> migrateFromChatId_;
MessagePtr pinnedMessage_; MessagePtr pinnedMessage_;
}; };

View file

@ -1,15 +0,0 @@
#ifndef TELEBOTXX_OPTIONAL_HPP
#define TELEBOTXX_OPTIONAL_HPP
#include <boost/optional.hpp>
namespace telebotxx {
template <typename T>
using optional = boost::optional<T>;
const auto none = boost::none;
}
#endif // TELEBOTXX_OPTIONAL_HPP

View file

@ -3,8 +3,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <variant>
#include <boost/variant/variant.hpp>
#define TELEBOTXX_DECLARE_BOOL_PARAM_CLASS(Name, DEFAULT) class Name \ #define TELEBOTXX_DECLARE_BOOL_PARAM_CLASS(Name, DEFAULT) class Name \
{ \ { \
@ -38,7 +37,7 @@ public:
const std::string getUsername() const; const std::string getUsername() const;
private: private:
Type type_; Type type_;
boost::variant<int, std::string> value_; std::variant<int, std::string> value_;
}; };
TELEBOTXX_DECLARE_STRING_PARAM_CLASS(Text); TELEBOTXX_DECLARE_STRING_PARAM_CLASS(Text);
@ -100,7 +99,7 @@ public:
private: private:
Type type_; Type type_;
boost::variant<int, Buffer, File, Url> value_; std::variant<int, Buffer, File, Url> value_;
}; };
} }

View file

@ -5,6 +5,7 @@
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <variant>
namespace telebotxx { namespace telebotxx {
@ -31,7 +32,7 @@ public:
private: private:
int id_; int id_;
Type type_; Type type_;
boost::variant<MessagePtr> value_; std::variant<MessagePtr> value_;
}; };
using Updates = std::vector<Update>; using Updates = std::vector<Update>;

View file

@ -1,9 +1,9 @@
#ifndef TELEBOTXX_USER_H #ifndef TELEBOTXX_USER_H
#define TELEBOTXX_USER_H #define TELEBOTXX_USER_H
#include "Optional.hpp"
#include <string> #include <string>
#include <memory> #include <memory>
#include <optional>
namespace telebotxx { namespace telebotxx {
@ -25,16 +25,16 @@ public:
void setFirstName(std::string firstName); void setFirstName(std::string firstName);
/// \brief Get last name /// \brief Get last name
const optional<std::string>& getLastName() const; const std::optional<std::string>& getLastName() const;
/// \brief Set last name /// \brief Set last name
void setLastName(optional<std::string> lastName); void setLastName(std::optional<std::string> lastName);
/// \brief Get username /// \brief Get username
const optional<std::string>& getUsername() const; const std::optional<std::string>& getUsername() const;
/// \brief Set username /// \brief Set username
void setUsername(optional<std::string> username); void setUsername(std::optional<std::string> username);
/// \brief Get string representation of user /// \brief Get string representation of user
const std::string toString() const; const std::string toString() const;
@ -42,8 +42,8 @@ public:
private: private:
int id_; int id_;
std::string firstName_; std::string firstName_;
optional<std::string> lastName_; std::optional<std::string> lastName_;
optional<std::string> username_; std::optional<std::string> username_;
}; };
std::ostream& operator<<(std::ostream& os, const User& user); std::ostream& operator<<(std::ostream& os, const User& user);

View file

@ -1,7 +1,5 @@
#include <telebotxx/Attachment.hpp> #include <telebotxx/Attachment.hpp>
#include <boost/variant.hpp>
namespace telebotxx { namespace telebotxx {
PhotoSize::PhotoSize() PhotoSize::PhotoSize()
@ -41,12 +39,12 @@ void PhotoSize::setHeight(int height)
height_ = height; height_ = height;
} }
const optional<int>& PhotoSize::getFileSize() const const std::optional<int>& PhotoSize::getFileSize() const
{ {
return fileSize_; return fileSize_;
} }
void PhotoSize::setFileSize(optional<int> fileSize) void PhotoSize::setFileSize(std::optional<int> fileSize)
{ {
fileSize_ = fileSize; fileSize_ = fileSize;
} }
@ -79,42 +77,42 @@ void Audio::setDuration(int duration)
duration_ = duration; duration_ = duration;
} }
const optional<std::string>& Audio::getPerformer() const const std::optional<std::string>& Audio::getPerformer() const
{ {
return performer_; return performer_;
} }
void Audio::setPerformer(optional<std::string> performer) void Audio::setPerformer(std::optional<std::string> performer)
{ {
performer_ = std::move(performer); performer_ = std::move(performer);
} }
const optional<std::string>& Audio::getTitle() const const std::optional<std::string>& Audio::getTitle() const
{ {
return title_; return title_;
} }
void Audio::setTitle(optional<std::string> title) void Audio::setTitle(std::optional<std::string> title)
{ {
title_ = title; title_ = title;
} }
const optional<std::string>& Audio::getMimeType() const const std::optional<std::string>& Audio::getMimeType() const
{ {
return mimeType_; return mimeType_;
} }
void Audio::setMimeType(optional<std::string> mimeType) void Audio::setMimeType(std::optional<std::string> mimeType)
{ {
mimeType_ = mimeType; mimeType_ = mimeType;
} }
const optional<int>& Audio::getFileSize() const const std::optional<int>& Audio::getFileSize() const
{ {
return fileSize_; return fileSize_;
} }
void Audio::setFileSize(optional<int> fileSize) void Audio::setFileSize(std::optional<int> fileSize)
{ {
fileSize_ = fileSize; fileSize_ = fileSize;
} }
@ -136,42 +134,42 @@ void Document::setFileId(std::string fileId)
fileId_ = fileId; fileId_ = fileId;
} }
const optional<PhotoSize>& Document::getThumb() const const std::optional<PhotoSize>& Document::getThumb() const
{ {
return thumb_; return thumb_;
} }
void Document::setThumb(optional<PhotoSize> thumb) void Document::setThumb(std::optional<PhotoSize> thumb)
{ {
thumb_ = thumb; thumb_ = thumb;
} }
const optional<std::string>& Document::getFileName() const const std::optional<std::string>& Document::getFileName() const
{ {
return fileName_; return fileName_;
} }
void Document::setFileName(optional<std::string> fileName) void Document::setFileName(std::optional<std::string> fileName)
{ {
fileName_ = fileName; fileName_ = fileName;
} }
const optional<std::string>& Document::getMimeType() const const std::optional<std::string>& Document::getMimeType() const
{ {
return mimeType_; return mimeType_;
} }
void Document::setMimeType(optional<std::string> mimeType) void Document::setMimeType(std::optional<std::string> mimeType)
{ {
mimeType_ = mimeType; mimeType_ = mimeType;
} }
const optional<int>& Document::getFileSize() const const std::optional<int>& Document::getFileSize() const
{ {
return fileSize_; return fileSize_;
} }
void Document::setFileSize(optional<int> fileSize) void Document::setFileSize(std::optional<int> fileSize)
{ {
fileSize_ = fileSize; fileSize_ = fileSize;
} }
@ -213,32 +211,32 @@ void Sticker::setHeight(int height)
height_ = height; height_ = height;
} }
const optional<PhotoSize>& Sticker::getThumb() const const std::optional<PhotoSize>& Sticker::getThumb() const
{ {
return thumb_; return thumb_;
} }
void Sticker::setThumb(optional<PhotoSize> thumb) void Sticker::setThumb(std::optional<PhotoSize> thumb)
{ {
thumb_ = thumb; thumb_ = thumb;
} }
const optional<std::string>& Sticker::getEmoji() const const std::optional<std::string>& Sticker::getEmoji() const
{ {
return emoji_; return emoji_;
} }
void Sticker::setEmoji(optional<std::string> emoji) void Sticker::setEmoji(std::optional<std::string> emoji)
{ {
emoji_ = emoji; emoji_ = emoji;
} }
const optional<int>& Sticker::getFileSize() const const std::optional<int>& Sticker::getFileSize() const
{ {
return fileSize_; return fileSize_;
} }
void Sticker::setFileSize(optional<int> fileSize) void Sticker::setFileSize(std::optional<int> fileSize)
{ {
fileSize_ = fileSize; fileSize_ = fileSize;
} }
@ -272,22 +270,22 @@ Attachment::Type Attachment::getType() const
const PhotoSizeArray& Attachment::getPhotoSizeArray() const const PhotoSizeArray& Attachment::getPhotoSizeArray() const
{ {
return boost::get<PhotoSizeArray>(value_); return std::get<PhotoSizeArray>(value_);
} }
const Audio& Attachment::getAudio() const const Audio& Attachment::getAudio() const
{ {
return boost::get<Audio>(value_);; return std::get<Audio>(value_);;
} }
const Document& Attachment::getDocument() const const Document& Attachment::getDocument() const
{ {
return boost::get<Document>(value_); return std::get<Document>(value_);
} }
const Sticker& Attachment::getSticker() const const Sticker& Attachment::getSticker() const
{ {
return boost::get<Sticker>(value_);; return std::get<Sticker>(value_);;
} }
} }

View file

@ -1,13 +1,5 @@
cmake_minimum_required(VERSION 2.8)
message(STATUS "Configuring telebotxx") message(STATUS "Configuring telebotxx")
include(${CMAKE_SOURCE_DIR}/cmake/RequireCXX14.cmake)
RequireCXX14()
find_package(Boost 1.56 REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
# Add required compiler flags # Add required compiler flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
@ -25,6 +17,11 @@ set(SOURCE_FILES Attachment.cpp
) )
add_library(telebotxx ${SOURCE_FILES}) add_library(telebotxx ${SOURCE_FILES})
target_link_libraries(telebotxx ${CPR_LIBRARIES}) target_include_directories(telebotxx PUBLIC ${telebotxx_SOURCE_DIR}/include)
target_link_libraries(telebotxx
PRIVATE
${CPR_LIBRARIES}
rapidjson
)
message(STATUS "Configuring telebotxx - done") message(STATUS "Configuring telebotxx - done")

View file

@ -30,42 +30,42 @@ void Chat::setType(Chat::Type type)
type_ = type; type_ = type;
} }
const optional<std::string>& Chat::getTitle() const const std::optional<std::string>& Chat::getTitle() const
{ {
return title_; return title_;
} }
void Chat::setTitle(optional<std::string> title) void Chat::setTitle(std::optional<std::string> title)
{ {
title_ = title; title_ = title;
} }
const optional<std::string>& Chat::getUsername() const const std::optional<std::string>& Chat::getUsername() const
{ {
return username_; return username_;
} }
void Chat::setUsername(optional<std::string> username) void Chat::setUsername(std::optional<std::string> username)
{ {
username_ = username; username_ = username;
} }
const optional<std::string>& Chat::getFirstName() const const std::optional<std::string>& Chat::getFirstName() const
{ {
return firstName_; return firstName_;
} }
void Chat::setFirstName(optional<std::string> firstName) void Chat::setFirstName(std::optional<std::string> firstName)
{ {
firstName_ = firstName; firstName_ = firstName;
} }
const optional<std::string>& Chat::getLastName() const const std::optional<std::string>& Chat::getLastName() const
{ {
return lastName_; return lastName_;
} }
void Chat::setLastName(optional<std::string> lastName) void Chat::setLastName(std::optional<std::string> lastName)
{ {
lastName_ = lastName; lastName_ = lastName;
} }

View file

@ -67,9 +67,9 @@ const rapidjson::Value& parseArray(const rapidjson::Value& parent, const char* n
} }
template <> template <>
optional<Chat> parse<Chat>(const rapidjson::Value& parent, const char* name, bool required) std::optional<Chat> parse<Chat>(const rapidjson::Value& parent, const char* name, bool required)
{ {
optional<Chat> chat; std::optional<Chat> chat;
bool found; bool found;
auto& obj = parseObject(parent, name, required, found); auto& obj = parseObject(parent, name, required, found);
if (found) if (found)
@ -87,9 +87,9 @@ optional<Chat> parse<Chat>(const rapidjson::Value& parent, const char* name, boo
} }
template <> template <>
optional<User> parse<User>(const rapidjson::Value& parent, const char* name, bool required) std::optional<User> parse<User>(const rapidjson::Value& parent, const char* name, bool required)
{ {
optional<User> user; std::optional<User> user;
bool found; bool found;
auto& obj = parseObject(parent, name, required, found); auto& obj = parseObject(parent, name, required, found);
if (found) if (found)
@ -113,9 +113,9 @@ PhotoSize parsePhotoSize(const rapidjson::Value& obj)
} }
template <> template <>
optional<PhotoSize> parse<PhotoSize>(const rapidjson::Value& parent, const char* name, bool required) std::optional<PhotoSize> parse<PhotoSize>(const rapidjson::Value& parent, const char* name, bool required)
{ {
optional<PhotoSize> photo; std::optional<PhotoSize> photo;
bool found; bool found;
auto& obj = parseObject(parent, name, required, found); auto& obj = parseObject(parent, name, required, found);
if (found) if (found)
@ -126,9 +126,9 @@ optional<PhotoSize> parse<PhotoSize>(const rapidjson::Value& parent, const char*
} }
template <> template <>
optional<PhotoSizeArray> parse<PhotoSizeArray>(const rapidjson::Value& parent, const char* name, bool required) std::optional<PhotoSizeArray> parse<PhotoSizeArray>(const rapidjson::Value& parent, const char* name, bool required)
{ {
optional<PhotoSizeArray> photos; std::optional<PhotoSizeArray> photos;
bool found; bool found;
auto& obj = parseArray(parent, name, required, found); auto& obj = parseArray(parent, name, required, found);
if (found) if (found)
@ -142,9 +142,9 @@ optional<PhotoSizeArray> parse<PhotoSizeArray>(const rapidjson::Value& parent, c
} }
template <> template <>
optional<Audio> parse<Audio>(const rapidjson::Value& parent, const char* name, bool required) std::optional<Audio> parse<Audio>(const rapidjson::Value& parent, const char* name, bool required)
{ {
optional<Audio> audio; std::optional<Audio> audio;
bool found; bool found;
auto& obj = parseObject(parent, name, required, found); auto& obj = parseObject(parent, name, required, found);
if (found) if (found)
@ -160,9 +160,9 @@ optional<Audio> parse<Audio>(const rapidjson::Value& parent, const char* name, b
} }
template <> template <>
optional<Document> parse<Document>(const rapidjson::Value& parent, const char* name, bool required) std::optional<Document> parse<Document>(const rapidjson::Value& parent, const char* name, bool required)
{ {
optional<Document> document; std::optional<Document> document;
bool found; bool found;
auto& obj = parseObject(parent, name, required, found); auto& obj = parseObject(parent, name, required, found);
if (found) if (found)
@ -178,9 +178,9 @@ optional<Document> parse<Document>(const rapidjson::Value& parent, const char* n
} }
template <> template <>
optional<Sticker> parse<Sticker>(const rapidjson::Value& parent, const char* name, bool required) std::optional<Sticker> parse<Sticker>(const rapidjson::Value& parent, const char* name, bool required)
{ {
optional<Sticker> sticker; std::optional<Sticker> sticker;
bool found; bool found;
auto& obj = parseObject(parent, name, required, found); auto& obj = parseObject(parent, name, required, found);
if (found) if (found)
@ -197,9 +197,9 @@ optional<Sticker> parse<Sticker>(const rapidjson::Value& parent, const char* nam
} }
template <> template <>
optional<Attachment> parse<Attachment>(const rapidjson::Value& parent, const char* name, bool required) std::optional<Attachment> parse<Attachment>(const rapidjson::Value& parent, const char* name, bool required)
{ {
optional<Attachment> attachment; std::optional<Attachment> attachment;
if (auto photo = allow<PhotoSizeArray>(parent, "photo")) if (auto photo = allow<PhotoSizeArray>(parent, "photo"))
attachment.emplace(std::move(*photo)); attachment.emplace(std::move(*photo));
else if (auto audio = allow<Audio>(parent, "audio")) else if (auto audio = allow<Audio>(parent, "audio"))

View file

@ -5,13 +5,13 @@
#include <telebotxx/Message.hpp> #include <telebotxx/Message.hpp>
#include <telebotxx/Update.hpp> #include <telebotxx/Update.hpp>
#include <telebotxx/User.hpp> #include <telebotxx/User.hpp>
#include <telebotxx/Optional.hpp>
#include <telebotxx/Exception.hpp> #include <telebotxx/Exception.hpp>
#include <memory>
#include <rapidjson/document.h> #include <rapidjson/document.h>
#include <memory>
#include <optional>
namespace telebotxx { namespace telebotxx {
const bool REQUIRED = true; const bool REQUIRED = true;
@ -34,7 +34,7 @@ template<> const std::string get(const rapidjson::Value& obj);
} }
template<typename T> template<typename T>
optional<T> parse(const rapidjson::Value& obj, const char* name, bool required) std::optional<T> parse(const rapidjson::Value& obj, const char* name, bool required)
{ {
if (obj.HasMember(name)) if (obj.HasMember(name))
{ {
@ -46,7 +46,7 @@ optional<T> parse(const rapidjson::Value& obj, const char* name, bool required)
else if (required) else if (required)
throw ParseError(std::string("Field '") + name + "' not found"); throw ParseError(std::string("Field '") + name + "' not found");
else else
return boost::none; return std::nullopt;
} }
template <typename T> template <typename T>
@ -56,7 +56,7 @@ T require(const rapidjson::Value& obj, const char* name)
} }
template <typename T> template <typename T>
optional<T> allow(const rapidjson::Value& obj, const char* name) std::optional<T> allow(const rapidjson::Value& obj, const char* name)
{ {
return parse<T>(obj, name, OPTIONAL); return parse<T>(obj, name, OPTIONAL);
} }
@ -68,7 +68,7 @@ bool check(const rapidjson::Value& obj, const char* name);
/// \param name field with Document object /// \param name field with Document object
/// \param required REQUIRED or OPTIONAL /// \param required REQUIRED or OPTIONAL
/// \return pointer to User /// \return pointer to User
template<> optional<User> parse<User>(const rapidjson::Value& parent, const char* name, bool required); template<> std::optional<User> parse<User>(const rapidjson::Value& parent, const char* name, bool required);
/// \brief Parse JSON object to Message /// \brief Parse JSON object to Message
/// \param parent reference to parent JSON object /// \param parent reference to parent JSON object

View file

@ -1,5 +1,7 @@
#include <telebotxx/Message.hpp> #include <telebotxx/Message.hpp>
#include <stdexcept>
namespace telebotxx { namespace telebotxx {
MessageEntity::MessageEntity() MessageEntity::MessageEntity()
@ -39,7 +41,7 @@ void MessageEntity::setLength(size_t length)
length_ = length; length_ = length;
} }
const optional<std::string>& MessageEntity::getUrl() const const std::optional<std::string>& MessageEntity::getUrl() const
{ {
return url_; return url_;
} }
@ -49,7 +51,7 @@ void MessageEntity::setUrl(std::string url)
url_ = std::move(url); url_ = std::move(url);
} }
const optional<User>& MessageEntity::getUser() const const std::optional<User>& MessageEntity::getUser() const
{ {
return user_; return user_;
} }
@ -108,12 +110,12 @@ void Message::setId(int id)
id_ = id; id_ = id;
} }
const boost::optional<User>& Message::getFrom() const const std::optional<User>& Message::getFrom() const
{ {
return from_; return from_;
} }
void Message::setFrom(optional<User> from) void Message::setFrom(std::optional<User> from)
{ {
from_ = std::move(from); from_ = std::move(from);
} }
@ -138,32 +140,32 @@ void Message::setChat(Chat chat)
chat_ = std::move(chat); chat_ = std::move(chat);
} }
const optional<User>& Message::getForwardFrom() const const std::optional<User>& Message::getForwardFrom() const
{ {
return forwardFrom_; return forwardFrom_;
} }
void Message::setForwardFrom(optional<User> forwardFrom) void Message::setForwardFrom(std::optional<User> forwardFrom)
{ {
forwardFrom_ = std::move(forwardFrom); forwardFrom_ = std::move(forwardFrom);
} }
const optional<Chat>& Message::getForwardFromChat() const const std::optional<Chat>& Message::getForwardFromChat() const
{ {
return forwardFromChat_; return forwardFromChat_;
} }
void Message::setForwardFromChat(optional<Chat> forwardFromChat) void Message::setForwardFromChat(std::optional<Chat> forwardFromChat)
{ {
forwardFromChat_ = std::move(forwardFromChat); forwardFromChat_ = std::move(forwardFromChat);
} }
const optional<time_t>& Message::getForwardDate() const const std::optional<time_t>& Message::getForwardDate() const
{ {
return forwardDate_; return forwardDate_;
} }
void Message::setForwardDate(optional<time_t> forwardDate) void Message::setForwardDate(std::optional<time_t> forwardDate)
{ {
forwardDate_ = forwardDate; forwardDate_ = forwardDate;
} }
@ -178,92 +180,92 @@ void Message::setReplyToMessage(MessagePtr replyToMessage)
replyToMessage_ = replyToMessage; replyToMessage_ = replyToMessage;
} }
const optional<time_t>& Message::getEditDate() const const std::optional<time_t>& Message::getEditDate() const
{ {
return editDate_; return editDate_;
} }
void Message::setEditDate(optional<time_t> editDate) void Message::setEditDate(std::optional<time_t> editDate)
{ {
editDate_ = editDate; editDate_ = editDate;
} }
const optional<std::string>& Message::getText() const const std::optional<std::string>& Message::getText() const
{ {
return text_; return text_;
} }
void Message::setText(optional<std::string> text) void Message::setText(std::optional<std::string> text)
{ {
text_ = std::move(text); text_ = std::move(text);
} }
const optional<MessageEntities>& Message::getEntities() const const std::optional<MessageEntities>& Message::getEntities() const
{ {
return entities_; return entities_;
} }
void Message::setEntities(optional<MessageEntities> entities) void Message::setEntities(std::optional<MessageEntities> entities)
{ {
entities_ = std::move(entities); entities_ = std::move(entities);
} }
const optional<Attachment>& Message::getAttachment() const const std::optional<Attachment>& Message::getAttachment() const
{ {
return attachment_; return attachment_;
} }
void Message::setAttachment(optional<Attachment> attachment) void Message::setAttachment(std::optional<Attachment> attachment)
{ {
attachment_ = std::move(attachment); attachment_ = std::move(attachment);
} }
const optional<std::string>& Message::getCaption() const const std::optional<std::string>& Message::getCaption() const
{ {
return caption_; return caption_;
} }
void Message::setCaption(optional<std::string> caption) void Message::setCaption(std::optional<std::string> caption)
{ {
caption_ = std::move(caption); caption_ = std::move(caption);
} }
const optional<User>& Message::getNewChatMember() const const std::optional<User>& Message::getNewChatMember() const
{ {
return newChatMember_; return newChatMember_;
} }
void Message::setNewChatMember(optional<User> newChatMember) void Message::setNewChatMember(std::optional<User> newChatMember)
{ {
newChatMember_ = std::move(newChatMember); newChatMember_ = std::move(newChatMember);
} }
const optional<User>& Message::getLeftChatMember() const const std::optional<User>& Message::getLeftChatMember() const
{ {
return leftChatMember_; return leftChatMember_;
} }
void Message::setLeftChatMember(optional<User> leftChatMember) void Message::setLeftChatMember(std::optional<User> leftChatMember)
{ {
leftChatMember_ = std::move(leftChatMember); leftChatMember_ = std::move(leftChatMember);
} }
const optional<std::string>& Message::getNewChatTitle() const const std::optional<std::string>& Message::getNewChatTitle() const
{ {
return newChatTitle_; return newChatTitle_;
} }
void Message::setNewChatTitle(optional<std::string> newChatTitle) void Message::setNewChatTitle(std::optional<std::string> newChatTitle)
{ {
newChatTitle_ = std::move(newChatTitle); newChatTitle_ = std::move(newChatTitle);
} }
const optional<PhotoSizeArray> Message::getNewChatPhoto() const const std::optional<PhotoSizeArray> Message::getNewChatPhoto() const
{ {
return newChatPhoto_; return newChatPhoto_;
} }
void Message::setNewChatPhoto(optional<PhotoSizeArray> newChatPhoto) void Message::setNewChatPhoto(std::optional<PhotoSizeArray> newChatPhoto)
{ {
newChatPhoto_ = std::move(newChatPhoto); newChatPhoto_ = std::move(newChatPhoto);
} }
@ -308,22 +310,22 @@ void Message::setChannelChatCreated(bool channelChatCreated)
channelChatCreated_ = channelChatCreated; channelChatCreated_ = channelChatCreated;
} }
const optional<std::int64_t>& Message::getMigrateToChatId() const const std::optional<std::int64_t>& Message::getMigrateToChatId() const
{ {
return migrateToChatId_; return migrateToChatId_;
} }
void Message::setMigrateToChatId(optional<std::int64_t> migrateToChatId) void Message::setMigrateToChatId(std::optional<std::int64_t> migrateToChatId)
{ {
migrateToChatId_ = migrateToChatId; migrateToChatId_ = migrateToChatId;
} }
const optional<std::int64_t>& Message::getMigrateFromChatId() const const std::optional<std::int64_t>& Message::getMigrateFromChatId() const
{ {
return migrateFromChatId_; return migrateFromChatId_;
} }
void Message::setMigrateFromChatId(optional<std::int64_t> migrateFromChatId) void Message::setMigrateFromChatId(std::optional<std::int64_t> migrateFromChatId)
{ {
migrateFromChatId_ = migrateFromChatId; migrateFromChatId_ = migrateFromChatId;
} }

View file

@ -1,7 +1,5 @@
#include <telebotxx/RequestOptions.hpp> #include <telebotxx/RequestOptions.hpp>
#include <boost/variant.hpp>
#define TELEBOTXX_DEFINE_BOOL_PARAM_CLASS(Name) Name::Name(bool value) : value_(value) { } \ #define TELEBOTXX_DEFINE_BOOL_PARAM_CLASS(Name) Name::Name(bool value) : value_(value) { } \
bool Name::getValue() const { return value_; } bool Name::getValue() const { return value_; }
@ -27,12 +25,12 @@ ChatId::Type ChatId::getType() const
const int ChatId::getId() const const int ChatId::getId() const
{ {
return boost::get<int>(value_); return std::get<int>(value_);
} }
const std::string ChatId::getUsername() const const std::string ChatId::getUsername() const
{ {
return boost::get<std::string>(value_); return std::get<std::string>(value_);
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -127,22 +125,22 @@ Photo::Type Photo::getType() const
int Photo::getId() const int Photo::getId() const
{ {
return boost::get<int>(value_); return std::get<int>(value_);
} }
const Buffer& Photo::getBuffer() const const Buffer& Photo::getBuffer() const
{ {
return boost::get<Buffer>(value_); return std::get<Buffer>(value_);
} }
const File& Photo::getFile() const const File& Photo::getFile() const
{ {
return boost::get<File>(value_); return std::get<File>(value_);
} }
const Url& Photo::getUrl() const const Url& Photo::getUrl() const
{ {
return boost::get<Url>(value_); return std::get<Url>(value_);
} }
} }

View file

@ -7,7 +7,7 @@
#include <rapidjson/writer.h> #include <rapidjson/writer.h>
#include <iostream> #include <iostream>
#include <boost/optional.hpp> #include <optional>
namespace telebotxx { namespace telebotxx {
@ -116,10 +116,10 @@ private:
std::string telegramMainUrl_; std::string telegramMainUrl_;
ChatId chatId_; ChatId chatId_;
Text text_; Text text_;
boost::optional<ParseMode> parseMode_; std::optional<ParseMode> parseMode_;
boost::optional<DisableWebPagePreview> disableWebPagePreview_; std::optional<DisableWebPagePreview> disableWebPagePreview_;
boost::optional<DisableNotification> disableNotification_; std::optional<DisableNotification> disableNotification_;
boost::optional<ReplyTo> replyToMessageId_; std::optional<ReplyTo> replyToMessageId_;
}; };
SendMessageRequest::SendMessageRequest(const std::string& telegramMainUrl, const ChatId& chat, const Text& text) SendMessageRequest::SendMessageRequest(const std::string& telegramMainUrl, const ChatId& chat, const Text& text)

View file

@ -7,7 +7,7 @@
#include <rapidjson/writer.h> #include <rapidjson/writer.h>
#include <iostream> #include <iostream>
#include <boost/optional.hpp> #include <optional>
namespace telebotxx { namespace telebotxx {
@ -51,8 +51,8 @@ public:
{ {
const char* data = photo_.getBuffer().data(); const char* data = photo_.getBuffer().data();
std::size_t size = photo_.getBuffer().size(); std::size_t size = photo_.getBuffer().size();
const std::string filename = photo_.getBuffer().filename(); std::string filename = photo_.getBuffer().filename();
multipart.parts.push_back({"photo", cpr::Buffer(data, data + size, filename)}); multipart.parts.push_back({"photo", cpr::Buffer(data, data + size, std::move(filename))});
} }
else if (photo_.getType() == Photo::Type::File) else if (photo_.getType() == Photo::Type::File)
multipart.parts.push_back({"photo", cpr::File(photo_.getFile().getValue())}); multipart.parts.push_back({"photo", cpr::File(photo_.getFile().getValue())});
@ -89,9 +89,9 @@ private:
std::string telegramMainUrl_; std::string telegramMainUrl_;
ChatId chatId_; ChatId chatId_;
Photo photo_; Photo photo_;
boost::optional<Caption> caption_; std::optional<Caption> caption_;
boost::optional<DisableNotification> disableNotification_; std::optional<DisableNotification> disableNotification_;
boost::optional<ReplyTo> replyToMessageId_; std::optional<ReplyTo> replyToMessageId_;
}; };
SendPhotoRequest::SendPhotoRequest(const std::string& telegramMainUrl, const ChatId& chat, const Photo& photo) SendPhotoRequest::SendPhotoRequest(const std::string& telegramMainUrl, const ChatId& chat, const Photo& photo)

View file

@ -1,5 +1,4 @@
#include <telebotxx/Update.hpp> #include <telebotxx/Update.hpp>
#include <boost/variant.hpp>
namespace telebotxx { namespace telebotxx {
@ -22,7 +21,7 @@ Update::Type Update::getType() const
MessagePtr Update::getMessage() const MessagePtr Update::getMessage() const
{ {
return boost::get<MessagePtr>(value_); return std::get<MessagePtr>(value_);
} }
} }

View file

@ -28,22 +28,22 @@ void User::setFirstName(std::string firstName)
firstName_ = std::move(firstName); firstName_ = std::move(firstName);
} }
const optional<std::string>& User::getLastName() const const std::optional<std::string>& User::getLastName() const
{ {
return lastName_; return lastName_;
} }
void User::setLastName(optional<std::string> lastName) void User::setLastName(std::optional<std::string> lastName)
{ {
lastName_ = std::move(lastName); lastName_ = std::move(lastName);
} }
const optional<std::string>& User::getUsername() const const std::optional<std::string>& User::getUsername() const
{ {
return username_; return username_;
} }
void User::setUsername(optional<std::string> username) void User::setUsername(std::optional<std::string> username)
{ {
username_ = std::move(username); username_ = std::move(username);
} }

View file

@ -1,24 +1,18 @@
cmake_minimum_required(VERSION 2.8)
if (POLICY CMP0037)
cmake_policy(SET CMP0037 OLD)
endif()
message(STATUS "Configuring telebotxx-test") message(STATUS "Configuring telebotxx-test")
include(${CMAKE_SOURCE_DIR}/cmake/RequireCXX14.cmake)
RequireCXX14()
add_definitions(-DBOOST_TEST_DYN_LINK)
find_package(Boost 1.56 REQUIRED COMPONENTS unit_test_framework system)
include_directories(${Boost_INCLUDE_DIRS})
# Add required compiler flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(SOURCE_FILES Dummy.cpp TestTypes.cpp TestApi.cpp) set(SOURCE_FILES TestApi.cpp)
add_executable(telebotxx-test ${SOURCE_FILES}) add_executable(telebotxx-test ${SOURCE_FILES})
target_link_libraries(telebotxx-test telebotxx stdc++ ${Boost_LIBRARIES}) target_link_libraries(telebotxx-test
telebotxx
Catch2::Catch2WithMain
rapidjson
)
add_custom_target(test COMMAND ${CMAKE_BINARY_DIR}/bin/telebotxx-test WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/tests" DEPENDS telebotxx-test) add_custom_target(test COMMAND $<TARGET_FILE:telebotxx-test>
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
DEPENDS telebotxx-test
)
message(STATUS "Configuring telebotxx-test - done") message(STATUS "Configuring telebotxx-test - done")

View file

@ -1,10 +0,0 @@
#define BOOST_TEST_MODULE AllTests
#include "TestGlobal.hpp"
#include <stdexcept>
BOOST_AUTO_TEST_CASE(Dummy)
{
PRINT_TESTNAME;
BOOST_REQUIRE(1 == 1);
BOOST_REQUIRE_THROW(throw 1, int);
}

View file

@ -1,4 +1,4 @@
#include "TestGlobal.hpp" #include <catch2/catch_all.hpp>
#include <telebotxx/BotApi.hpp> #include <telebotxx/BotApi.hpp>
#include <telebotxx/Logging.hpp> #include <telebotxx/Logging.hpp>
@ -7,34 +7,34 @@
#include <fstream> #include <fstream>
#include <rapidjson/document.h> #include <rapidjson/document.h>
#include <rapidjson/filereadstream.h> #include <rapidjson/istreamwrapper.h>
std::unique_ptr<telebotxx::BotApi> bot; #include <iostream>
const std::string CONFIG_FILE_NAME = "config.json"; const char* CONFIG_FILE_NAME = "config.json";
using namespace telebotxx;
struct Config
{
std::string token; std::string token;
std::string chat; std::string chat;
std::string photoFile; std::string photoFile;
std::string photoUrl; std::string photoUrl;
};
std::unique_ptr<Config> config;
struct TestConfig std::unique_ptr<Config> readConfig()
{ {
TestConfig()
{
std::cout << "Performing tests initialization..." << std::endl;
using namespace rapidjson; using namespace rapidjson;
FILE *pFile = fopen(CONFIG_FILE_NAME.c_str(), "rb");
if (pFile == NULL) std::ifstream file(CONFIG_FILE_NAME);
if (file.fail())
throw std::runtime_error("Can not open config file"); throw std::runtime_error("Can not open config file");
char buffer[2048]; IStreamWrapper is(file);
FileReadStream is(pFile, buffer, sizeof(buffer));
rapidjson::Document document; rapidjson::Document document;
document.ParseStream<0, UTF8<>, FileReadStream>(is); document.ParseStream(is);
Config config;
if (!document.IsObject() && document.HasParseError()) if (!document.IsObject() && document.HasParseError())
throw std::invalid_argument("Can not parse config file"); throw std::invalid_argument("Can not parse config file");
@ -42,7 +42,7 @@ struct TestConfig
// Read token // Read token
if (document.HasMember("token")) if (document.HasMember("token"))
if (document["token"].IsString()) if (document["token"].IsString())
token = document["token"].GetString(); config.token = document["token"].GetString();
else else
throw std::invalid_argument("Config error: 'token' must be unsigned int value."); throw std::invalid_argument("Config error: 'token' must be unsigned int value.");
else else
@ -51,7 +51,7 @@ struct TestConfig
// Read chat // Read chat
if (document.HasMember("chat")) if (document.HasMember("chat"))
if (document["chat"].IsString()) if (document["chat"].IsString())
chat = document["chat"].GetString(); config.chat = document["chat"].GetString();
else else
throw std::invalid_argument("Config error: 'chat' must be unsigned int value."); throw std::invalid_argument("Config error: 'chat' must be unsigned int value.");
else else
@ -60,7 +60,7 @@ struct TestConfig
// Read photo filename // Read photo filename
if (document.HasMember("photo")) if (document.HasMember("photo"))
if (document["photo"].IsString()) if (document["photo"].IsString())
photoFile = document["photo"].GetString(); config.photoFile = document["photo"].GetString();
else else
throw std::invalid_argument("Config error: 'photo' must be unsigned int value."); throw std::invalid_argument("Config error: 'photo' must be unsigned int value.");
else else
@ -69,145 +69,131 @@ struct TestConfig
// Read photo URL // Read photo URL
if (document.HasMember("photoURL")) if (document.HasMember("photoURL"))
if (document["photoURL"].IsString()) if (document["photoURL"].IsString())
photoUrl = document["photoURL"].GetString(); config.photoUrl = document["photoURL"].GetString();
else else
throw std::invalid_argument("Config error: 'photoURL' must be unsigned int value."); throw std::invalid_argument("Config error: 'photoURL' must be unsigned int value.");
else else
throw std::invalid_argument("Config error: 'photoURL' not set."); throw std::invalid_argument("Config error: 'photoURL' not set.");
telebotxx::setDebugMode(true); telebotxx::setDebugMode(true);
return std::make_unique<Config>(std::move(config));
} }
~TestConfig() using namespace telebotxx;
std::unique_ptr<BotApi> bot;
TEST_CASE("Read tests configuration")
{ {
std::cout << "Performing tests cleanup..." << std::endl; REQUIRE_NOTHROW(config = readConfig());
} REQUIRE(config);
};
BOOST_GLOBAL_FIXTURE(TestConfig);
BOOST_AUTO_TEST_SUITE(TestSend)
BOOST_AUTO_TEST_CASE(DefaultConstructor)
{
PRINT_TESTNAME;
BOOST_REQUIRE_NO_THROW(bot.reset(new BotApi(token)));
} }
BOOST_AUTO_TEST_CASE(SendMessage) TEST_CASE("Default constructor", "[API]")
{ {
PRINT_TESTNAME; REQUIRE(config);
BOOST_REQUIRE(bot); REQUIRE_NOTHROW(bot.reset(new BotApi(config->token)));
BOOST_REQUIRE_NO_THROW(bot->sendMessage(ChatId{chat},
Text{"Sample text"}
));
} }
BOOST_AUTO_TEST_CASE(SendMessageWithMarkdown) TEST_CASE("Send text message", "[API]")
{ {
PRINT_TESTNAME; REQUIRE(bot);
BOOST_REQUIRE(bot); REQUIRE_NOTHROW(bot->sendMessage(ChatId{config->chat}, Text{"Sample text"}));
BOOST_REQUIRE_NO_THROW(bot->sendMessage(ChatId{chat}, }
TEST_CASE("Send message with markdown", "[API]")
{
REQUIRE(bot);
REQUIRE_NOTHROW(bot->sendMessage(ChatId{config->chat},
Text{"[Sample text in markdown](http://google.com/)"}, Text{"[Sample text in markdown](http://google.com/)"},
ParseMode::Markdown ParseMode::Markdown
)); ));
} }
BOOST_AUTO_TEST_CASE(SendMessageWithHtml) TEST_CASE("Send message with HTML", "[API]")
{ {
PRINT_TESTNAME; REQUIRE(bot);
BOOST_REQUIRE(bot); REQUIRE_NOTHROW(bot->sendMessage(ChatId{config->chat},
BOOST_REQUIRE_NO_THROW(bot->sendMessage(ChatId{chat}, Text{
Text{"<a href=\"http://google.com/\">Sample text in HTML</a>"}, "<a href=\"http://google.com/\">Sample text in HTML</a>"},
ParseMode::Html ParseMode::Html
)); ));
} }
BOOST_AUTO_TEST_CASE(SendMessageWithoutPreview) TEST_CASE("Send message without preview", "[API]")
{ {
PRINT_TESTNAME; REQUIRE(bot);
BOOST_REQUIRE(bot); REQUIRE_NOTHROW(bot->sendMessage(ChatId{config->chat},
BOOST_REQUIRE_NO_THROW(bot->sendMessage(ChatId{chat},
Text{"http://google.com/"}, Text{"http://google.com/"},
DisableWebPagePreview() DisableWebPagePreview()
)); ));
} }
BOOST_AUTO_TEST_CASE(SendMessageWithoutNotification) TEST_CASE("Send message without notification", "[API]")
{ {
PRINT_TESTNAME; REQUIRE(bot);
BOOST_REQUIRE(bot); REQUIRE_NOTHROW(bot->sendMessage(ChatId{config->chat},
BOOST_REQUIRE_NO_THROW(bot->sendMessage(ChatId{chat},
Text{"Message without notification"}, Text{"Message without notification"},
DisableNotification() DisableNotification()
)); ));
} }
BOOST_AUTO_TEST_CASE(SendPhotoFile) TEST_CASE("Send photo from file", "[API]")
{ {
PRINT_TESTNAME; REQUIRE(bot);
BOOST_REQUIRE(bot); REQUIRE_NOTHROW(bot->sendPhoto(config->chat, Photo{File{config->photoFile}}));
BOOST_REQUIRE_NO_THROW(bot->sendPhoto(chat,
Photo{File{photoFile}}
));
} }
BOOST_AUTO_TEST_CASE(SendPhotoFileWithCaption) TEST_CASE("Send photo from file with caption", "[API]")
{ {
PRINT_TESTNAME;
BOOST_REQUIRE(bot); REQUIRE(bot);
BOOST_REQUIRE_NO_THROW(bot->sendPhoto(chat, REQUIRE_NOTHROW(bot->sendPhoto(config->chat,
Photo{File{photoFile}}, Photo{File{config->photoFile}},
Caption{"Photo with caption"} Caption{"Photo with caption"}
)); ));
} }
BOOST_AUTO_TEST_CASE(SendPhotoInMemory) TEST_CASE("Send photo from memory", "[API]")
{ {
PRINT_TESTNAME; REQUIRE(bot);
BOOST_REQUIRE(bot); std::ifstream file(config->photoFile, std::ios::binary | std::ios::ate);
std::ifstream file(photoFile, std::ios::binary | std::ios::ate);
std::size_t size = static_cast<std::size_t>(file.tellg()); std::size_t size = static_cast<std::size_t>(file.tellg());
file.seekg(0, std::ios::beg); file.seekg(0, std::ios::beg);
std::vector<char> buffer(size); std::vector<char> buffer(size);
BOOST_REQUIRE(file.read(buffer.data(), size)); REQUIRE(file.read(buffer.data(), size));
BOOST_REQUIRE_NO_THROW(bot->sendPhoto(chat, REQUIRE_NOTHROW(bot->sendPhoto(config->chat,
Photo{Buffer{buffer.data(), size, photoFile}}, Photo{Buffer{buffer.data(), size, config->photoFile}},
Caption{"Photo sent in-memory"} Caption{"Photo sent in-memory"}
)); ));
} }
BOOST_AUTO_TEST_CASE(SendPhotoUrl) TEST_CASE("Send photo by URL", "[API]")
{ {
PRINT_TESTNAME; REQUIRE(bot);
BOOST_REQUIRE(bot); REQUIRE_NOTHROW(bot->sendPhoto(config->chat,
BOOST_REQUIRE_NO_THROW(bot->sendPhoto(chat, Photo{Url{config->photoUrl}},
Photo{Url{photoUrl}},
Caption{"Photo sent by URL"} Caption{"Photo sent by URL"}
)); ));
} }
BOOST_AUTO_TEST_CASE(SendPhotoWithoutNotification) TEST_CASE("Send photo without notification", "[API]")
{ {
PRINT_TESTNAME; REQUIRE(bot);
BOOST_REQUIRE(bot); REQUIRE_NOTHROW(bot->sendPhoto(config->chat,
BOOST_REQUIRE_NO_THROW(bot->sendPhoto(chat, Photo{File{config->photoFile}},
Photo{File{photoFile}},
Caption{"Photo without notification"}, Caption{"Photo without notification"},
DisableNotification() DisableNotification()
)); ));
} }
BOOST_AUTO_TEST_SUITE_END() TEST_CASE("Get updates", "[API]")
BOOST_AUTO_TEST_SUITE(TestParse)
BOOST_AUTO_TEST_CASE(GetUpdates)
{ {
PRINT_TESTNAME; REQUIRE(bot);
BOOST_REQUIRE(bot);
Updates updates; Updates updates;
BOOST_REQUIRE_NO_THROW(updates = bot->getUpdates()); REQUIRE_NOTHROW(updates = bot->getUpdates());
for (auto update : updates) for (auto update : updates)
{ {
switch (update.getType()) switch (update.getType())
@ -227,5 +213,3 @@ BOOST_AUTO_TEST_SUITE(TestParse)
} }
} }
} }
BOOST_AUTO_TEST_SUITE_END()

View file

@ -1,13 +0,0 @@
#ifndef TELEBOTXX_TEST_GLOBAL_HPP
#define TELEBOTXX_TEST_GLOBAL_HPP
#include <boost/test/unit_test.hpp>
#include <iostream>
using namespace boost::unit_test;
#define BOOST_TEST_SUITE_NAME (boost::unit_test::framework::get<boost::unit_test::test_suite>(boost::unit_test::framework::current_test_case().p_parent_id).p_name)
#define BOOST_TEST_NAME (boost::unit_test::framework::current_test_case().p_name)
#define PRINT_TESTNAME std::cout << "\x1B[36mRunning unit test " << BOOST_TEST_SUITE_NAME << "::" << BOOST_TEST_NAME << "...\x1B[0m" << std::endl;
#endif // TELEBOTXX_TEST_GLOBAL_HPP

View file

@ -1,47 +0,0 @@
#include "TestGlobal.hpp"
#include <telebotxx/User.hpp>
using namespace telebotxx;
BOOST_AUTO_TEST_SUITE(TestUser)
BOOST_AUTO_TEST_CASE(DefaultConstructor)
{
PRINT_TESTNAME;
BOOST_REQUIRE_NO_THROW(User user);
}
BOOST_AUTO_TEST_CASE(CopyConstructor)
{
PRINT_TESTNAME;
User other;
other.setId(1);
other.setFirstName(std::string("John"));
other.setLastName(std::string("Smith"));
other.setUsername(std::string("john_smith"));
std::unique_ptr<User> user;
BOOST_REQUIRE_NO_THROW(user.reset(new User(other)));
BOOST_REQUIRE_EQUAL(user->getId(), 1);
BOOST_REQUIRE_EQUAL(user->getFirstName(), "John");
BOOST_REQUIRE_EQUAL(*user->getLastName(), "Smith");
BOOST_REQUIRE_EQUAL(*user->getUsername(), "john_smith");
}
BOOST_AUTO_TEST_CASE(MoveConstructor)
{
PRINT_TESTNAME;
User other;
other.setId(1);
other.setFirstName(std::string("John"));
other.setLastName(std::string("Smith"));
other.setUsername(std::string("john_smith"));
std::unique_ptr<User> user;
BOOST_REQUIRE_NO_THROW(user.reset(new User(std::move(other))));
BOOST_REQUIRE_EQUAL(user->getId(), 1);
BOOST_REQUIRE_EQUAL(user->getFirstName(), "John");
BOOST_REQUIRE_EQUAL(*user->getLastName(), "Smith");
BOOST_REQUIRE_EQUAL(*user->getUsername(), "john_smith");
}
BOOST_AUTO_TEST_SUITE_END()