Merge branch 'dev' into inline_keyboard

This commit is contained in:
Kirill Kirilenko 2020-11-30 16:37:33 +03:00
commit aa5c220a75
55 changed files with 3497 additions and 3392 deletions

110
.clang-format Normal file
View file

@ -0,0 +1,110 @@
---
BasedOnStyle: WebKit
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveBitFields: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: DontAlign
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: Inline
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: false
AfterStruct: true
AfterUnion: true
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: true
BeforeWhile: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
ColumnLimit: 100
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
FixNamespaceComments: true
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^".*"'
Priority: 1
- Regex: '^<telebotxx/.*>'
Priority: 2
- Regex: '^<.*([.]h|[.]hpp)>'
Priority: 3
- Regex: '^<.*>'
Priority: 4
IndentCaseBlocks: false
IndentCaseLabels: false
IndentExternBlock: NoIndent
IndentGotoLabels: false
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
Language: Cpp
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
PenaltyExcessCharacter: 10
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
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: c++14
StatementMacros: ['Q_UNUSED']
TabWidth: 4
UseCRLF: false
UseTab: ForIndentation
...

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(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin") set(CMAKE_CXX_STANDARD 17)
set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/lib") set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
# Build and include Curl for People if (TELEBOTXX_USE_LIBCXX)
set(BUILD_CPR_TESTS OFF CACHE BOOL "Do not build cpr tests") if (UNIX)
find_package(CURL) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
if(CURL_FOUND) link_libraries(c++abi)
set(USE_SYSTEM_CURL ON CACHE BOOL "Use the system curl for faster builds") endif()
if(MSVC)
# TODO
message(WARNING "libc++ with MSVC is not yet supported")
endif()
endif() endif()
add_subdirectory(${PROJECT_SOURCE_DIR}/ext/cpr) set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin")
include_directories(${CPR_INCLUDE_DIRS}) set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/lib")
# Include RapidJSON headers # Build dependencies
include_directories(${PROJECT_SOURCE_DIR}/ext/rapidjson/include) add_subdirectory(ext)
# 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 21293329ccc5d3976787d851da62e55864862431 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 b4dae2b77dc71aa2f129bcd9aa8cb09632b4b299 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 <vector>
#include <memory> #include <memory>
#include <boost/variant/variant.hpp> #include <optional>
#include <string>
#include <variant>
#include <vector>
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,9 +158,9 @@ public:
private: private:
Type type_; Type type_;
boost::variant<PhotoSizeArray, Audio, Document, Sticker> value_; std::variant<PhotoSizeArray, Audio, Document, Sticker> value_;
}; };
} } // namespace telebotxx
#endif // TELEBOTXX_ATTACHMENT_HPP #endif // TELEBOTXX_ATTACHMENT_HPP

View file

@ -1,14 +1,14 @@
#ifndef TELEBOTXX_BOTAPI_HPP #ifndef TELEBOTXX_BOTAPI_HPP
#define TELEBOTXX_BOTAPI_HPP #define TELEBOTXX_BOTAPI_HPP
#include "User.hpp"
#include "Message.hpp" #include "Message.hpp"
#include "Update.hpp"
#include "SendMessageRequest.hpp" #include "SendMessageRequest.hpp"
#include "SendPhotoRequest.hpp" #include "SendPhotoRequest.hpp"
#include "Update.hpp"
#include "User.hpp"
#include <string>
#include <memory> #include <memory>
#include <string>
namespace telebotxx { namespace telebotxx {
@ -28,7 +28,6 @@ void setRequestOption(RequestType& request, T&& t, Ts&&... ts)
class BotApi class BotApi
{ {
public: public:
/// \param [in] token bot's secret token /// \param [in] token bot's secret token
BotApi(const std::string& token); BotApi(const std::string& token);
@ -52,7 +51,8 @@ public:
template <typename... Ts> template <typename... Ts>
Message sendMessage(ChatId&& chatId, Text&& text, Ts&&... args) Message sendMessage(ChatId&& chatId, Text&& text, Ts&&... args)
{ {
SendMessageRequest request(getTelegramMainUrl(), std::forward<ChatId>(chatId), std::forward<Text>(text)); SendMessageRequest request(getTelegramMainUrl(), std::forward<ChatId>(chatId),
std::forward<Text>(text));
setRequestOption(request, std::forward<Ts>(args)...); setRequestOption(request, std::forward<Ts>(args)...);
return request.execute(); return request.execute();
} }
@ -71,7 +71,8 @@ public:
template <typename... Ts> template <typename... Ts>
Message sendPhoto(ChatId&& chatId, Photo&& photo, Ts&&... args) Message sendPhoto(ChatId&& chatId, Photo&& photo, Ts&&... args)
{ {
SendPhotoRequest request(getTelegramMainUrl(), std::forward<ChatId>(chatId), std::forward<Photo>(photo)); SendPhotoRequest request(getTelegramMainUrl(), std::forward<ChatId>(chatId),
std::forward<Photo>(photo));
setRequestOption(request, std::forward<Ts>(args)...); setRequestOption(request, std::forward<Ts>(args)...);
return request.execute(); return request.execute();
} }
@ -85,12 +86,12 @@ 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_;
}; };
} } // namespace telebotxx
#endif // TELEBOTXX_BOTAPI_HPP #endif // TELEBOTXX_BOTAPI_HPP

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 <memory>
#include <cstdint> #include <cstdint>
#include <memory>
#include <optional>
#include <string>
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,15 +45,15 @@ 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_;
}; };
Chat::Type chatTypeFromString(const std::string& str); Chat::Type chatTypeFromString(const std::string& str);
} } // namespace telebotxx
#endif // TELEBOTXX_CHAT_HPP #endif // TELEBOTXX_CHAT_HPP

View file

@ -8,29 +8,20 @@ namespace telebotxx {
class ParseError : public std::invalid_argument class ParseError : public std::invalid_argument
{ {
public: public:
ParseError(const std::string& message) ParseError(const std::string& message) : std::invalid_argument(message) {}
: std::invalid_argument(message)
{
}
}; };
class ApiError : public std::runtime_error class ApiError : public std::runtime_error
{ {
public: public:
ApiError(int code, std::string message) ApiError(int code, std::string message) : std::runtime_error(std::move(message)), code_(code) {}
: std::runtime_error(std::move(message)), code_(code)
{
}
int getCode() const int getCode() const { return code_; }
{
return code_;
}
protected: protected:
int code_; int code_;
}; };
} } // namespace telebotxx
#endif // TELEBOTXX_EXCEPTION_HPP #endif // TELEBOTXX_EXCEPTION_HPP

View file

@ -8,6 +8,6 @@ extern bool debugMode;
/// \brief Enable/disable debug output /// \brief Enable/disable debug output
void setDebugMode(bool enabled); void setDebugMode(bool enabled);
} } // namespace telebotxx
#endif // TELEBOTXX_LOGGING_HPP #endif // TELEBOTXX_LOGGING_HPP

View file

@ -1,15 +1,14 @@
#ifndef TELEBOTXX_MESSAGE_HPP #ifndef TELEBOTXX_MESSAGE_HPP
#define TELEBOTXX_MESSAGE_HPP #define TELEBOTXX_MESSAGE_HPP
#include "User.hpp"
#include "Chat.hpp"
#include "Attachment.hpp" #include "Attachment.hpp"
#include "Optional.hpp" #include "Chat.hpp"
#include "User.hpp"
#include <vector>
#include <ctime> #include <ctime>
#include <memory> #include <memory>
#include <boost/variant/variant.hpp> #include <optional>
#include <vector>
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,43 +130,43 @@ 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_;
}; };
} } // namespace telebotxx
#endif // TELEBOTXX_MESSAGE_HPP #endif // TELEBOTXX_MESSAGE_HPP

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

@ -2,27 +2,30 @@
#define TELEBOTXX_REQUEST_OPTIONS_HPP #define TELEBOTXX_REQUEST_OPTIONS_HPP
#include <string> #include <string>
#include <variant>
#include <vector> #include <vector>
#include <boost/variant/variant.hpp> #define TELEBOTXX_DECLARE_BOOL_PARAM_CLASS(Name, DEFAULT) \
class Name \
{ \
public: \
explicit Name(bool value = DEFAULT); \
bool getValue() const; \
\
private: \
bool value_; \
};
#define TELEBOTXX_DECLARE_BOOL_PARAM_CLASS(Name, DEFAULT) class Name \ #define TELEBOTXX_DECLARE_STRING_PARAM_CLASS(Name) \
{ \ class Name \
public: \ { \
explicit Name(bool value = DEFAULT); \ public: \
bool getValue() const; \ explicit Name(const std::string& value); \
private: \ const std::string& getValue() const; \
bool value_; \ \
}; private: \
std::string value_; \
#define TELEBOTXX_DECLARE_STRING_PARAM_CLASS(Name) class Name \ };
{ \
public: \
explicit Name(const std::string& value); \
const std::string& getValue() const; \
private: \
std::string value_; \
};
namespace telebotxx { namespace telebotxx {
@ -32,13 +35,18 @@ public:
ChatId(int); ChatId(int);
ChatId(const std::string&); ChatId(const std::string&);
enum class Type { Id, Username }; enum class Type
{
Id,
Username
};
Type getType() const; Type getType() const;
const int getId() const; const int getId() const;
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);
@ -60,6 +68,7 @@ class ReplyTo
public: public:
explicit ReplyTo(int id); explicit ReplyTo(int id);
int value() const; int value() const;
private: private:
int id_; int id_;
}; };
@ -67,13 +76,14 @@ private:
class Buffer class Buffer
{ {
public: public:
Buffer(const char *buffer, std::size_t size, const std::string& filename); Buffer(const char* buffer, std::size_t size, const std::string& filename);
explicit Buffer(const std::vector<char>& data, const std::string& filename); explicit Buffer(const std::vector<char>& data, const std::string& filename);
const char *data() const; const char* data() const;
const std::size_t size() const; const std::size_t size() const;
const std::string filename() const; const std::string filename() const;
private: private:
const char *data_; const char* data_;
std::size_t size_; std::size_t size_;
std::string filename_; std::string filename_;
}; };
@ -90,7 +100,13 @@ public:
explicit Photo(const File&); explicit Photo(const File&);
explicit Photo(const Url&); explicit Photo(const Url&);
enum class Type { Id, Buffer, File, Url }; enum class Type
{
Id,
Buffer,
File,
Url
};
Type getType() const; Type getType() const;
int getId() const; int getId() const;
@ -100,7 +116,7 @@ public:
private: private:
Type type_; Type type_;
boost::variant<int, Buffer, File, Url> value_; std::variant<int, Buffer, File, Url> value_;
}; };
TELEBOTXX_DECLARE_STRING_PARAM_CLASS(CallbackData) TELEBOTXX_DECLARE_STRING_PARAM_CLASS(CallbackData)
@ -120,7 +136,13 @@ public:
InlineKeyboardButton(InlineKeyboardButton&&); InlineKeyboardButton(InlineKeyboardButton&&);
~InlineKeyboardButton(); ~InlineKeyboardButton();
enum class ActionType { Url, CallbackData, SwitchInlineQuery, SwitchInlineQueryCurrentChat }; enum class ActionType
{
Url,
CallbackData,
SwitchInlineQuery,
SwitchInlineQueryCurrentChat
};
ActionType getActionType() const; ActionType getActionType() const;
const std::string& getText() const; const std::string& getText() const;
@ -135,7 +157,7 @@ public:
private: private:
ActionType actionType_; ActionType actionType_;
std::string text_; std::string text_;
boost::variant<Url, CallbackData, SwitchInlineQuery, SwitchInlineQueryCurrentChat> value_; std::variant<Url, CallbackData, SwitchInlineQuery, SwitchInlineQueryCurrentChat> value_;
// \todo CallbackGame // \todo CallbackGame
}; };
@ -154,7 +176,6 @@ private:
class ReplyKeyboardMarkup class ReplyKeyboardMarkup
{ {
}; };
class ReplyMarkup class ReplyMarkup
@ -166,7 +187,13 @@ public:
ReplyMarkup(ReplyMarkup&&); ReplyMarkup(ReplyMarkup&&);
~ReplyMarkup(); ~ReplyMarkup();
enum class Type { InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply }; enum class Type
{
InlineKeyboardMarkup,
ReplyKeyboardMarkup,
ReplyKeyboardRemove,
ForceReply
};
Type getType() const; Type getType() const;
const InlineKeyboardMarkup& getInlineKeyboardMarkup() const; const InlineKeyboardMarkup& getInlineKeyboardMarkup() const;
@ -176,9 +203,9 @@ public:
private: private:
Type type_; Type type_;
boost::variant<InlineKeyboardMarkup, ReplyKeyboardMarkup> value_; std::variant<InlineKeyboardMarkup, ReplyKeyboardMarkup> value_;
}; };
} } // namespace telebotxx
#endif // TELEBOTXX_REQUEST_OPTIONS_HPP #endif // TELEBOTXX_REQUEST_OPTIONS_HPP

View file

@ -1,11 +1,11 @@
#ifndef TELEBOTXX_SEND_MESSAGE_REQUEST_HPP #ifndef TELEBOTXX_SEND_MESSAGE_REQUEST_HPP
#define TELEBOTXX_SEND_MESSAGE_REQUEST_HPP #define TELEBOTXX_SEND_MESSAGE_REQUEST_HPP
#include <telebotxx/RequestOptions.hpp> #include "Message.hpp"
#include <telebotxx/Message.hpp> #include "RequestOptions.hpp"
#include <string>
#include <memory> #include <memory>
#include <string>
namespace telebotxx { namespace telebotxx {
@ -34,6 +34,6 @@ private:
std::unique_ptr<Impl> impl_; std::unique_ptr<Impl> impl_;
}; };
} } // namespace telebotxx
#endif // TELEBOTXX_SEND_MESSAGE_REQUEST_HPP #endif // TELEBOTXX_SEND_MESSAGE_REQUEST_HPP

View file

@ -1,11 +1,11 @@
#ifndef TELEBOTXX_SEND_PHOTO_REQUEST_HPP #ifndef TELEBOTXX_SEND_PHOTO_REQUEST_HPP
#define TELEBOTXX_SEND_PHOTO_REQUEST_HPP #define TELEBOTXX_SEND_PHOTO_REQUEST_HPP
#include <telebotxx/RequestOptions.hpp> #include "Message.hpp"
#include <telebotxx/Message.hpp> #include "RequestOptions.hpp"
#include <string>
#include <memory> #include <memory>
#include <string>
namespace telebotxx { namespace telebotxx {
@ -32,6 +32,6 @@ private:
std::unique_ptr<Impl> impl_; std::unique_ptr<Impl> impl_;
}; };
} } // namespace telebotxx
#endif // TELEBOTXX_SEND_PHOTO_REQUEST_HPP #endif // TELEBOTXX_SEND_PHOTO_REQUEST_HPP

View file

@ -3,8 +3,9 @@
#include "Message.hpp" #include "Message.hpp"
#include <vector>
#include <memory> #include <memory>
#include <variant>
#include <vector>
namespace telebotxx { namespace telebotxx {
@ -31,11 +32,11 @@ 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>;
} } // namespace telebotxx
#endif // TELEBOTXX_UPDATE_HPP #endif // TELEBOTXX_UPDATE_HPP

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 <memory> #include <memory>
#include <optional>
#include <string>
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,12 +42,12 @@ 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);
} } // namespace telebotxx
#endif // TELEBOTXX_USER_H #endif // TELEBOTXX_USER_H

View file

@ -1,13 +1,8 @@
#include <telebotxx/Attachment.hpp> #include <telebotxx/Attachment.hpp>
#include <boost/variant.hpp>
namespace telebotxx { namespace telebotxx {
PhotoSize::PhotoSize() PhotoSize::PhotoSize() : width_(-1), height_(-1), fileSize_(-1)
: width_(-1),
height_(-1),
fileSize_(-1)
{ {
} }
@ -41,21 +36,19 @@ 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;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Audio::Audio() Audio::Audio() : duration_(-1), fileSize_(-1)
: duration_(-1),
fileSize_(-1)
{ {
} }
@ -79,50 +72,49 @@ 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;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Document::Document() Document::Document() : fileSize_(-1)
: fileSize_(-1)
{ {
} }
@ -136,50 +128,49 @@ 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;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Sticker::Sticker() Sticker::Sticker() : fileSize_(-1)
: fileSize_(-1)
{ {
} }
@ -213,32 +204,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;
} }
@ -246,22 +237,19 @@ void Sticker::setFileSize(optional<int> fileSize)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Attachment::Attachment(PhotoSizeArray photos) Attachment::Attachment(PhotoSizeArray photos)
: type_(Type::PhotoSizeArray), value_(std::move(photos)) : type_(Type::PhotoSizeArray), value_(std::move(photos))
{ {
} }
Attachment::Attachment(Audio audio) Attachment::Attachment(Audio audio) : type_(Type::Audio), value_(std::move(audio))
: type_(Type::Audio), value_(std::move(audio))
{ {
} }
Attachment::Attachment(Document document) Attachment::Attachment(Document document) : type_(Type::Document), value_(std::move(document))
: type_(Type::Document), value_(std::move(document))
{ {
} }
Attachment::Attachment(Sticker sticker) Attachment::Attachment(Sticker sticker) : type_(Type::Sticker), value_(std::move(sticker))
: type_(Type::Sticker), value_(std::move(sticker))
{ {
} }
@ -272,22 +260,24 @@ 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_);
;
} }
} } // namespace telebotxx

View file

@ -1,22 +1,21 @@
#include <telebotxx/BotApi.hpp> #include "BotApi.hpp"
#include <telebotxx/Exception.hpp>
#include <telebotxx/Logging.hpp> #include "Exception.hpp"
#include "JsonObjects.hpp" #include "JsonObjects.hpp"
#include "Logging.hpp"
#include <cpr/cpr.h>
#include <rapidjson/writer.h>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <rapidjson/writer.h>
#include <cpr/cpr.h>
namespace telebotxx { namespace telebotxx {
class BotApi::Impl class BotApi::Impl
{ {
public: public:
Impl(const std::string& token) Impl(const std::string& token) : token_(token)
: token_(token)
{ {
telegramMainUrl_ = "https://api.telegram.org/bot" + token_; telegramMainUrl_ = "https://api.telegram.org/bot" + token_;
botUser_ = getMe(); botUser_ = getMe();
@ -37,14 +36,12 @@ public:
return require<User>(doc, "result"); return require<User>(doc, "result");
} }
inline Message sendPhoto(const std::string& chat, const std::string& filename, const std::string& caption) inline Message
sendPhoto(const std::string& chat, const std::string& filename, const std::string& caption)
{ {
auto r = cpr::Post(cpr::Url{telegramMainUrl_ + "/sendPhoto"}, auto r = cpr::Post(
cpr::Multipart{{"chat_id", chat}, cpr::Url{telegramMainUrl_ + "/sendPhoto"},
{"photo", cpr::File{filename}}, cpr::Multipart{{"chat_id", chat}, {"photo", cpr::File{filename}}, {"caption", caption}});
{"caption", caption}
}
);
auto& response = r.text; auto& response = r.text;
if (debugMode) if (debugMode)
@ -58,7 +55,8 @@ public:
return *parseMessage(doc, "result", REQUIRED); return *parseMessage(doc, "result", REQUIRED);
} }
inline Message sendPhotoUrl(const std::string& chat, const std::string& url, const std::string& caption) inline Message
sendPhotoUrl(const std::string& chat, const std::string& url, const std::string& caption)
{ {
// Construct JSON body // Construct JSON body
using namespace rapidjson; using namespace rapidjson;
@ -77,9 +75,7 @@ public:
std::string request = s.GetString(); std::string request = s.GetString();
auto r = cpr::Post(cpr::Url{telegramMainUrl_ + "/sendPhoto"}, auto r = cpr::Post(cpr::Url{telegramMainUrl_ + "/sendPhoto"},
cpr::Header{{"Content-Type", "application/json"}}, cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{request});
cpr::Body{request}
);
auto& response = r.text; auto& response = r.text;
if (debugMode) if (debugMode)
@ -121,9 +117,7 @@ public:
std::string request = s.GetString(); std::string request = s.GetString();
auto r = cpr::Post(cpr::Url{telegramMainUrl_ + "/getUpdates"}, auto r = cpr::Post(cpr::Url{telegramMainUrl_ + "/getUpdates"},
cpr::Header{{"Content-Type", "application/json"}}, cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{request});
cpr::Body{request}
);
auto& response = r.text; auto& response = r.text;
if (debugMode) if (debugMode)
@ -136,20 +130,15 @@ public:
return parseUpdates(doc, "result"); return parseUpdates(doc, "result");
} }
std::string getTelegramMainUrl() const std::string getTelegramMainUrl() const { return telegramMainUrl_; }
{
return telegramMainUrl_;
}
private: private:
std::string token_; std::string token_;
std::string telegramMainUrl_; std::string telegramMainUrl_;
User botUser_; User botUser_;
}; };
BotApi::BotApi(const std::string& token) BotApi::BotApi(const std::string& token) : impl_(std::make_unique<Impl>(token))
: impl_(std::make_unique<Impl>(token))
{ {
} }
@ -162,13 +151,15 @@ User BotApi::getMe()
Message BotApi::sendMessage(ChatId&& chatId, Text&& text) Message BotApi::sendMessage(ChatId&& chatId, Text&& text)
{ {
SendMessageRequest request(getTelegramMainUrl(), std::forward<ChatId>(chatId), std::forward<Text>(text)); SendMessageRequest request(getTelegramMainUrl(), std::forward<ChatId>(chatId),
std::forward<Text>(text));
return request.execute(); return request.execute();
} }
Message BotApi::sendPhoto(ChatId&& chatId, Photo&& photo) Message BotApi::sendPhoto(ChatId&& chatId, Photo&& photo)
{ {
SendPhotoRequest request(getTelegramMainUrl(), std::forward<ChatId>(chatId), std::forward<Photo>(photo)); SendPhotoRequest request(getTelegramMainUrl(), std::forward<ChatId>(chatId),
std::forward<Photo>(photo));
return request.execute(); return request.execute();
} }
@ -182,4 +173,4 @@ std::string BotApi::getTelegramMainUrl() const
return impl_->getTelegramMainUrl(); return impl_->getTelegramMainUrl();
} }
} } // namespace telebotxx

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")
@ -26,6 +18,12 @@ 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_include_directories(telebotxx PRIVATE ${telebotxx_SOURCE_DIR}/include/telebotxx)
target_link_libraries(telebotxx
PRIVATE
${CPR_LIBRARIES}
rapidjson
)
message(STATUS "Configuring telebotxx - done") message(STATUS "Configuring telebotxx - done")

View file

@ -1,12 +1,10 @@
#include <telebotxx/Chat.hpp> #include "Chat.hpp"
#include <stdexcept> #include <stdexcept>
namespace telebotxx { namespace telebotxx {
Chat::Chat() Chat::Chat() : id_(-1), type_(Type::Private), allAdmins_(false)
: id_(-1),
type_(Type::Private),
allAdmins_(false)
{ {
} }
@ -30,42 +28,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;
} }
@ -94,4 +92,4 @@ Chat::Type chatTypeFromString(const std::string& str)
throw std::invalid_argument("Unknown chat type"); throw std::invalid_argument("Unknown chat type");
} }
} } // namespace telebotxx

View file

@ -4,17 +4,49 @@
namespace telebotxx { namespace telebotxx {
namespace impl { namespace impl {
template<> bool is<int>(const rapidjson::Value& obj) { return obj.IsInt(); } template <>
template<> bool is<std::int64_t>(const rapidjson::Value& obj) { return obj.IsInt64(); } bool is<int>(const rapidjson::Value& obj)
template<> bool is<bool>(const rapidjson::Value& obj) { return obj.IsBool(); } {
template<> bool is<std::string>(const rapidjson::Value& obj) { return obj.IsString(); } return obj.IsInt();
template<> const int get(const rapidjson::Value& obj) { return obj.GetInt(); }
template<> const std::int64_t get(const rapidjson::Value& obj) { return obj.GetInt64(); }
template<> const bool get(const rapidjson::Value& obj) { return obj.GetBool(); }
template<> const std::string get(const rapidjson::Value& obj) { return obj.GetString(); }
} }
template <>
bool is<std::int64_t>(const rapidjson::Value& obj)
{
return obj.IsInt64();
}
template <>
bool is<bool>(const rapidjson::Value& obj)
{
return obj.IsBool();
}
template <>
bool is<std::string>(const rapidjson::Value& obj)
{
return obj.IsString();
}
template <>
const int get(const rapidjson::Value& obj)
{
return obj.GetInt();
}
template <>
const std::int64_t get(const rapidjson::Value& obj)
{
return obj.GetInt64();
}
template <>
const bool get(const rapidjson::Value& obj)
{
return obj.GetBool();
}
template <>
const std::string get(const rapidjson::Value& obj)
{
return obj.GetString();
}
} // namespace impl
bool check(const rapidjson::Value& obj, const char* name) bool check(const rapidjson::Value& obj, const char* name)
{ {
@ -24,7 +56,8 @@ bool check(const rapidjson::Value& obj, const char* name)
return false; return false;
} }
const rapidjson::Value& parseObject(const rapidjson::Value& parent, const char* name, bool required, bool& found) const rapidjson::Value&
parseObject(const rapidjson::Value& parent, const char* name, bool required, bool& found)
{ {
if (parent.HasMember(name)) if (parent.HasMember(name))
{ {
@ -45,7 +78,8 @@ const rapidjson::Value& parseObject(const rapidjson::Value& parent, const char*
} }
} }
const rapidjson::Value& parseArray(const rapidjson::Value& parent, const char* name, bool required, bool& found) const rapidjson::Value&
parseArray(const rapidjson::Value& parent, const char* name, bool required, bool& found)
{ {
if (parent.HasMember(name)) if (parent.HasMember(name))
{ {
@ -67,9 +101,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 +121,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 +147,10 @@ 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 +161,10 @@ 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 +178,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 +196,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 +214,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 +233,10 @@ 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"))
@ -230,7 +267,7 @@ std::unique_ptr<Message> parseMessage(const rapidjson::Value& parent, const char
message->setReplyToMessage(parseMessage(obj, "reply_to_message", OPTIONAL)); message->setReplyToMessage(parseMessage(obj, "reply_to_message", OPTIONAL));
message->setEditDate(allow<std::int64_t>(obj, "edit_date")); message->setEditDate(allow<std::int64_t>(obj, "edit_date"));
message->setText(parse<std::string>(obj, "text", OPTIONAL)); message->setText(parse<std::string>(obj, "text", OPTIONAL));
//message->setEntities(parseEntities(obj, "entities", OPTIONAL)); // message->setEntities(parseEntities(obj, "entities", OPTIONAL));
message->setAttachment(allow<Attachment>(obj, "")); message->setAttachment(allow<Attachment>(obj, ""));
message->setCaption(allow<std::string>(obj, "caption")); message->setCaption(allow<std::string>(obj, "caption"));
message->setNewChatMember(allow<User>(obj, "new_chat_member")); message->setNewChatMember(allow<User>(obj, "new_chat_member"));
@ -295,4 +332,4 @@ void checkResponse(const rapidjson::Document& doc)
} }
} }
} } // namespace telebotxx

View file

@ -1,17 +1,17 @@
#ifndef TELEBOTXX_JSON_OBJECTS_HPP #ifndef TELEBOTXX_JSON_OBJECTS_HPP
#define TELEBOTXX_JSON_OBJECTS_HPP #define TELEBOTXX_JSON_OBJECTS_HPP
#include <telebotxx/Attachment.hpp> #include "Attachment.hpp"
#include <telebotxx/Message.hpp> #include "Exception.hpp"
#include <telebotxx/Update.hpp> #include "Message.hpp"
#include <telebotxx/User.hpp> #include "Update.hpp"
#include <telebotxx/Optional.hpp> #include "User.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;
@ -19,22 +19,32 @@ const bool OPTIONAL = false;
namespace impl { namespace impl {
template<typename T> bool is(const rapidjson::Value& obj); template <typename T>
template<> bool is<int>(const rapidjson::Value& obj); bool is(const rapidjson::Value& obj);
template<> bool is<std::int64_t>(const rapidjson::Value& obj); template <>
template<> bool is<bool>(const rapidjson::Value& obj); bool is<int>(const rapidjson::Value& obj);
template<> bool is<std::string>(const rapidjson::Value& obj); template <>
bool is<std::int64_t>(const rapidjson::Value& obj);
template <>
bool is<bool>(const rapidjson::Value& obj);
template <>
bool is<std::string>(const rapidjson::Value& obj);
template<typename T> const T get(const rapidjson::Value& obj); template <typename T>
template<> const int get(const rapidjson::Value& obj); const T get(const rapidjson::Value& obj);
template<> const std::int64_t get(const rapidjson::Value& obj); template <>
template<> const bool get(const rapidjson::Value& obj); const int get(const rapidjson::Value& obj);
template<> const std::string get(const rapidjson::Value& obj); template <>
const std::int64_t get(const rapidjson::Value& obj);
template <>
const bool get(const rapidjson::Value& obj);
template <>
const std::string get(const rapidjson::Value& obj);
} } // namespace impl
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 +56,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 +66,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 +78,8 @@ 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
@ -89,6 +100,6 @@ Updates parseUpdates(const rapidjson::Value& parent, const char* name);
/// \param doc reference to JSON document /// \param doc reference to JSON document
void checkResponse(const rapidjson::Document& doc); void checkResponse(const rapidjson::Document& doc);
} } // namespace telebotxx
#endif // TELEBOTXX_JSON_OBJECTS_HPP #endif // TELEBOTXX_JSON_OBJECTS_HPP

View file

@ -1,4 +1,4 @@
#include <telebotxx/Logging.hpp> #include "Logging.hpp"
namespace telebotxx { namespace telebotxx {
@ -9,4 +9,4 @@ void setDebugMode(bool enabled)
debugMode = enabled; debugMode = enabled;
} }
} } // namespace telebotxx

View file

@ -1,11 +1,10 @@
#include <telebotxx/Message.hpp> #include "Message.hpp"
#include <stdexcept>
namespace telebotxx { namespace telebotxx {
MessageEntity::MessageEntity() MessageEntity::MessageEntity() : type_(Type::Mention), offset_(-1), length_(0)
: type_(Type::Mention),
offset_(-1),
length_(0)
{ {
} }
@ -39,7 +38,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 +48,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_;
} }
@ -90,11 +89,11 @@ MessageEntity::Type messageEntityTypeFromString(const std::string& str)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Message::Message() Message::Message()
: id_(-1), : id_(-1),
deleteChatPhoto_(false), deleteChatPhoto_(false),
groupChatCreated_(false), groupChatCreated_(false),
superGroupChatCreated_(false), superGroupChatCreated_(false),
channelChatCreated_(false) channelChatCreated_(false)
{ {
} }
@ -108,12 +107,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 +137,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 +177,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 +307,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;
} }
@ -338,4 +337,4 @@ void Message::setPinnedMessage(MessagePtr pinnedMessage)
pinnedMessage_ = pinnedMessage; pinnedMessage_ = pinnedMessage;
} }
} } // namespace telebotxx

View file

@ -2,7 +2,8 @@
namespace telebotxx { namespace telebotxx {
void writeInlineKeyboardButton(rapidjson::Writer<rapidjson::StringBuffer>& writer, const InlineKeyboardButton& button) void writeInlineKeyboardButton(rapidjson::Writer<rapidjson::StringBuffer>& writer,
const InlineKeyboardButton& button)
{ {
writer.StartObject(); writer.StartObject();
@ -11,36 +12,37 @@ void writeInlineKeyboardButton(rapidjson::Writer<rapidjson::StringBuffer>& write
switch (button.getActionType()) switch (button.getActionType())
{ {
case InlineKeyboardButton::ActionType::Url: case InlineKeyboardButton::ActionType::Url:
{ {
writer.String("url"); writer.String("url");
writer.String(button.getUrl().getValue().c_str()); writer.String(button.getUrl().getValue().c_str());
break; break;
} }
case InlineKeyboardButton::ActionType::CallbackData: case InlineKeyboardButton::ActionType::CallbackData:
{ {
writer.String("callback_data"); writer.String("callback_data");
writer.String(button.getCallbackData().getValue().c_str()); writer.String(button.getCallbackData().getValue().c_str());
break; break;
} }
case InlineKeyboardButton::ActionType::SwitchInlineQuery: case InlineKeyboardButton::ActionType::SwitchInlineQuery:
{ {
writer.String("switch_inline_query"); writer.String("switch_inline_query");
writer.String(button.getSwitchInlineQuery().getValue().c_str()); writer.String(button.getSwitchInlineQuery().getValue().c_str());
break; break;
} }
case InlineKeyboardButton::ActionType::SwitchInlineQueryCurrentChat: case InlineKeyboardButton::ActionType::SwitchInlineQueryCurrentChat:
{ {
writer.String("switch_inline_query_current_chat"); writer.String("switch_inline_query_current_chat");
writer.String(button.getSwitchInlineQueryCurrentChat().getValue().c_str()); writer.String(button.getSwitchInlineQueryCurrentChat().getValue().c_str());
break; break;
} }
} }
writer.EndObject(); writer.EndObject();
} }
void writeInlineKeyboardMarkup(rapidjson::Writer<rapidjson::StringBuffer>& writer, const InlineKeyboardMarkup& markup) void writeInlineKeyboardMarkup(rapidjson::Writer<rapidjson::StringBuffer>& writer,
const InlineKeyboardMarkup& markup)
{ {
writer.StartObject(); writer.StartObject();
writer.String("inline_keyboard"); writer.String("inline_keyboard");
@ -63,4 +65,4 @@ void writeReplyMarkup(rapidjson::Writer<rapidjson::StringBuffer>& writer, const
writeInlineKeyboardMarkup(writer, markup.getInlineKeyboardMarkup()); writeInlineKeyboardMarkup(writer, markup.getInlineKeyboardMarkup());
} }
} } // namespace telebotxx

View file

@ -1,7 +1,7 @@
#ifndef TELEBOTXX_REPLY_MARKUP_HPP #ifndef TELEBOTXX_REPLY_MARKUP_HPP
#define TELEBOTXX_REPLY_MARKUP_HPP #define TELEBOTXX_REPLY_MARKUP_HPP
#include <telebotxx/RequestOptions.hpp> #include "RequestOptions.hpp"
#include <rapidjson/writer.h> #include <rapidjson/writer.h>

View file

@ -1,22 +1,20 @@
#include <telebotxx/RequestOptions.hpp> #include "RequestOptions.hpp"
#include <boost/variant.hpp> #define TELEBOTXX_DEFINE_BOOL_PARAM_CLASS(Name) \
Name::Name(bool value) : value_(value) {} \
bool Name::getValue() const { return value_; }
#define TELEBOTXX_DEFINE_BOOL_PARAM_CLASS(Name) Name::Name(bool value) : value_(value) { } \ #define TELEBOTXX_DEFINE_STRING_PARAM_CLASS(Name) \
bool Name::getValue() const { return value_; } Name::Name(const std::string& value) : value_(value) {} \
const std::string& Name::getValue() const { return value_; }
#define TELEBOTXX_DEFINE_STRING_PARAM_CLASS(Name) Name::Name(const std::string& value) : value_(value) { } \
const std::string& Name::getValue() const { return value_; }
namespace telebotxx { namespace telebotxx {
ChatId::ChatId(int id) ChatId::ChatId(int id) : type_(Type::Id), value_(id)
: type_(Type::Id), value_(id)
{ {
} }
ChatId::ChatId(const std::string& str) ChatId::ChatId(const std::string& str) : type_(Type::Username), value_(str)
: type_(Type::Username), value_(str)
{ {
} }
@ -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_);
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -53,8 +51,7 @@ TELEBOTXX_DEFINE_BOOL_PARAM_CLASS(DisableNotification)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
ReplyTo::ReplyTo(int id) ReplyTo::ReplyTo(int id) : id_(id)
: id_(id)
{ {
} }
@ -66,12 +63,12 @@ int ReplyTo::value() const
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Buffer::Buffer(const char* buffer, std::size_t size, const std::string& filename) Buffer::Buffer(const char* buffer, std::size_t size, const std::string& filename)
: data_(buffer), size_(size), filename_(filename) : data_(buffer), size_(size), filename_(filename)
{ {
} }
Buffer::Buffer(const std::vector<char>& data, const std::string& filename) Buffer::Buffer(const std::vector<char>& data, const std::string& filename)
: data_(data.data()), size_(data.size()), filename_(filename) : data_(data.data()), size_(data.size()), filename_(filename)
{ {
} }
@ -100,23 +97,19 @@ TELEBOTXX_DEFINE_STRING_PARAM_CLASS(Url)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Photo::Photo(int id) Photo::Photo(int id) : type_(Type::Id), value_(id)
: type_(Type::Id), value_(id)
{ {
} }
Photo::Photo(const Buffer& buffer) Photo::Photo(const Buffer& buffer) : type_(Type::Buffer), value_(buffer)
: type_(Type::Buffer), value_(buffer)
{ {
} }
Photo::Photo(const File& file) Photo::Photo(const File& file) : type_(Type::File), value_(file)
: type_(Type::File), value_(file)
{ {
} }
Photo::Photo(const Url& url) Photo::Photo(const Url& url) : type_(Type::Url), value_(url)
: type_(Type::Url), value_(url)
{ {
} }
@ -127,22 +120,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_);
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -160,23 +153,26 @@ TELEBOTXX_DEFINE_STRING_PARAM_CLASS(SwitchInlineQueryCurrentChat)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
InlineKeyboardButton::InlineKeyboardButton(const std::string& text, const Url& url) InlineKeyboardButton::InlineKeyboardButton(const std::string& text, const Url& url)
: actionType_(ActionType::Url), text_(text), value_(url) : actionType_(ActionType::Url), text_(text), value_(url)
{ {
} }
InlineKeyboardButton::InlineKeyboardButton(const std::string& text, const CallbackData& callbackData) InlineKeyboardButton::InlineKeyboardButton(const std::string& text, const CallbackData& callbackData)
: actionType_(ActionType::CallbackData), text_(text), value_(callbackData) : actionType_(ActionType::CallbackData), text_(text), value_(callbackData)
{
}
InlineKeyboardButton::InlineKeyboardButton(const std::string& text, const SwitchInlineQuery& switchInlineQuery)
: actionType_(ActionType::SwitchInlineQuery), text_(text), value_(switchInlineQuery)
{ {
} }
InlineKeyboardButton::InlineKeyboardButton(const std::string& text, InlineKeyboardButton::InlineKeyboardButton(const std::string& text,
const SwitchInlineQueryCurrentChat& switchInlineQueryCurrentChat) const SwitchInlineQuery& switchInlineQuery)
: actionType_(ActionType::SwitchInlineQueryCurrentChat), text_(text), value_(switchInlineQueryCurrentChat) : actionType_(ActionType::SwitchInlineQuery), text_(text), value_(switchInlineQuery)
{
}
InlineKeyboardButton::InlineKeyboardButton(const std::string& text,
const SwitchInlineQueryCurrentChat& switchInlineQueryCurrentChat)
: actionType_(ActionType::SwitchInlineQueryCurrentChat),
text_(text),
value_(switchInlineQueryCurrentChat)
{ {
} }
@ -198,22 +194,22 @@ const std::string& InlineKeyboardButton::getText() const
const Url& InlineKeyboardButton::getUrl() const const Url& InlineKeyboardButton::getUrl() const
{ {
return boost::get<Url>(value_);; return std::get<Url>(value_);
} }
const CallbackData& InlineKeyboardButton::getCallbackData() const const CallbackData& InlineKeyboardButton::getCallbackData() const
{ {
return boost::get<CallbackData>(value_); return std::get<CallbackData>(value_);
} }
const SwitchInlineQuery& InlineKeyboardButton::getSwitchInlineQuery() const const SwitchInlineQuery& InlineKeyboardButton::getSwitchInlineQuery() const
{ {
return boost::get<SwitchInlineQuery>(value_); return std::get<SwitchInlineQuery>(value_);
} }
const SwitchInlineQueryCurrentChat& InlineKeyboardButton::getSwitchInlineQueryCurrentChat() const const SwitchInlineQueryCurrentChat& InlineKeyboardButton::getSwitchInlineQueryCurrentChat() const
{ {
return boost::get<SwitchInlineQueryCurrentChat>(value_); return std::get<SwitchInlineQueryCurrentChat>(value_);
} }
void InlineKeyboardButton::swap(InlineKeyboardButton& other) void InlineKeyboardButton::swap(InlineKeyboardButton& other)
@ -245,12 +241,12 @@ const std::vector<InlineKeyboardButtonRow>& InlineKeyboardMarkup::getRows() cons
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
ReplyMarkup::ReplyMarkup(const InlineKeyboardMarkup& keyboard) ReplyMarkup::ReplyMarkup(const InlineKeyboardMarkup& keyboard)
: type_(Type::InlineKeyboardMarkup), value_(keyboard) : type_(Type::InlineKeyboardMarkup), value_(keyboard)
{ {
} }
ReplyMarkup::ReplyMarkup(const ReplyKeyboardMarkup& keyboard) ReplyMarkup::ReplyMarkup(const ReplyKeyboardMarkup& keyboard)
: type_(Type::ReplyKeyboardMarkup), value_(keyboard) : type_(Type::ReplyKeyboardMarkup), value_(keyboard)
{ {
} }
@ -265,7 +261,7 @@ ReplyMarkup::Type ReplyMarkup::getType() const
const InlineKeyboardMarkup& ReplyMarkup::getInlineKeyboardMarkup() const const InlineKeyboardMarkup& ReplyMarkup::getInlineKeyboardMarkup() const
{ {
return boost::get<InlineKeyboardMarkup>(value_); return std::get<InlineKeyboardMarkup>(value_);
} }
void ReplyMarkup::swap(ReplyMarkup& other) void ReplyMarkup::swap(ReplyMarkup& other)
@ -281,4 +277,4 @@ const ReplyMarkup& ReplyMarkup::operator=(ReplyMarkup other)
return *this; return *this;
} }
} } // namespace telebotxx

View file

@ -1,6 +1,7 @@
#include <telebotxx/SendMessageRequest.hpp> #include "SendMessageRequest.hpp"
#include <telebotxx/Logging.hpp>
#include "JsonObjects.hpp" #include "JsonObjects.hpp"
#include "Logging.hpp"
#include "ReplyMarkup.hpp" #include "ReplyMarkup.hpp"
#include <cpr/cpr.h> #include <cpr/cpr.h>
@ -8,7 +9,7 @@
#include <rapidjson/writer.h> #include <rapidjson/writer.h>
#include <iostream> #include <iostream>
#include <boost/optional.hpp> #include <optional>
namespace telebotxx { namespace telebotxx {
@ -16,14 +17,11 @@ class SendMessageRequest::Impl
{ {
public: public:
Impl(const std::string& telegramMainUrl, const ChatId& chat, const Text& text) Impl(const std::string& telegramMainUrl, const ChatId& chat, const Text& text)
: telegramMainUrl_(telegramMainUrl), chatId_(chat), text_(text) : telegramMainUrl_(telegramMainUrl), chatId_(chat), text_(text)
{ {
} }
void setParseMode(ParseMode mode) void setParseMode(ParseMode mode) { parseMode_ = mode; }
{
parseMode_ = mode;
}
void setDisableWebPagePreview(const DisableWebPagePreview& disableWebPagePreview) void setDisableWebPagePreview(const DisableWebPagePreview& disableWebPagePreview)
{ {
@ -40,10 +38,7 @@ public:
replyToMessageId_ = replyToMessageId; replyToMessageId_ = replyToMessageId;
} }
void setReplyMarkup(const ReplyMarkup& replyMarkup) void setReplyMarkup(const ReplyMarkup& replyMarkup) { replyMarkup_ = replyMarkup; }
{
replyMarkup_ = replyMarkup;
}
Message execute() Message execute()
{ {
@ -68,8 +63,9 @@ public:
if (parseMode_) if (parseMode_)
{ {
writer.String("parse_mode"); writer.String("parse_mode");
writer.String( writer.String((parseMode_ == ParseMode::Markdown) ? "Markdown"
(parseMode_ == ParseMode::Markdown) ? "Markdown" : (parseMode_ == ParseMode::Html) ? "HTML" : "Plain"); : (parseMode_ == ParseMode::Html) ? "HTML"
: "Plain");
} }
// Add disable_web_page_preview // Add disable_web_page_preview
@ -107,9 +103,7 @@ public:
if (debugMode) if (debugMode)
std::cout << "Request: " << request << std::endl; std::cout << "Request: " << request << std::endl;
auto r = cpr::Post(cpr::Url{telegramMainUrl_ + "/sendMessage"}, auto r = cpr::Post(cpr::Url{telegramMainUrl_ + "/sendMessage"},
cpr::Header{{"Content-Type", "application/json"}}, cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{request});
cpr::Body{request}
);
auto& response = r.text; auto& response = r.text;
if (debugMode) if (debugMode)
@ -127,15 +121,17 @@ 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_;
boost::optional<ReplyMarkup> replyMarkup_; std::optional<ReplyMarkup> replyMarkup_;
}; };
SendMessageRequest::SendMessageRequest(const std::string& telegramMainUrl, const ChatId& chat, const Text& text) SendMessageRequest::SendMessageRequest(const std::string& telegramMainUrl,
: impl_(std::make_unique<Impl>(telegramMainUrl, chat, text)) const ChatId& chat,
const Text& text)
: impl_(std::make_unique<Impl>(telegramMainUrl, chat, text))
{ {
} }
@ -198,4 +194,4 @@ Message SendMessageRequest::execute()
return impl_->execute(); return impl_->execute();
} }
} } // namespace telebotxx

View file

@ -1,6 +1,7 @@
#include <telebotxx/SendPhotoRequest.hpp> #include "SendPhotoRequest.hpp"
#include <telebotxx/Logging.hpp>
#include "JsonObjects.hpp" #include "JsonObjects.hpp"
#include "Logging.hpp"
#include "ReplyMarkup.hpp" #include "ReplyMarkup.hpp"
#include <cpr/cpr.h> #include <cpr/cpr.h>
@ -8,7 +9,7 @@
#include <rapidjson/writer.h> #include <rapidjson/writer.h>
#include <iostream> #include <iostream>
#include <boost/optional.hpp> #include <optional>
namespace telebotxx { namespace telebotxx {
@ -16,14 +17,11 @@ class SendPhotoRequest::Impl
{ {
public: public:
Impl(const std::string& telegramMainUrl, const ChatId& chat, const Photo& photo) Impl(const std::string& telegramMainUrl, const ChatId& chat, const Photo& photo)
: telegramMainUrl_(telegramMainUrl), chatId_(chat), photo_(photo) : telegramMainUrl_(telegramMainUrl), chatId_(chat), photo_(photo)
{ {
} }
void setCaption(const Caption& caption) void setCaption(const Caption& caption) { caption_ = caption; }
{
caption_ = caption;
}
void setDisableNotification(const DisableNotification& disableNotification) void setDisableNotification(const DisableNotification& disableNotification)
{ {
@ -35,10 +33,7 @@ public:
replyToMessageId_ = replyToMessageId; replyToMessageId_ = replyToMessageId;
} }
void setReplyMarkup(const ReplyMarkup& replyMarkup) void setReplyMarkup(const ReplyMarkup& replyMarkup) { replyMarkup_ = replyMarkup; }
{
replyMarkup_ = replyMarkup;
}
Message execute() Message execute()
{ {
@ -57,8 +52,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())});
@ -106,14 +101,16 @@ 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_;
boost::optional<ReplyMarkup> replyMarkup_; std::optional<ReplyMarkup> replyMarkup_;
}; };
SendPhotoRequest::SendPhotoRequest(const std::string& telegramMainUrl, const ChatId& chat, const Photo& photo) SendPhotoRequest::SendPhotoRequest(const std::string& telegramMainUrl,
: impl_(std::make_unique<Impl>(telegramMainUrl, chat, photo)) const ChatId& chat,
const Photo& photo)
: impl_(std::make_unique<Impl>(telegramMainUrl, chat, photo))
{ {
} }
@ -166,4 +163,4 @@ Message SendPhotoRequest::execute()
return impl_->execute(); return impl_->execute();
} }
} } // namespace telebotxx

View file

@ -1,12 +1,9 @@
#include <telebotxx/Update.hpp> #include "Update.hpp"
#include <boost/variant.hpp>
namespace telebotxx { namespace telebotxx {
Update::Update(int id, Type type, std::unique_ptr<Message> message) Update::Update(int id, Type type, std::unique_ptr<Message> message)
: id_(id), : id_(id), type_(type), value_(std::move(message))
type_(type),
value_(std::move(message))
{ {
} }
@ -22,7 +19,7 @@ Update::Type Update::getType() const
MessagePtr Update::getMessage() const MessagePtr Update::getMessage() const
{ {
return boost::get<MessagePtr>(value_); return std::get<MessagePtr>(value_);
} }
} } // namespace telebotxx

View file

@ -1,10 +1,10 @@
#include <telebotxx/User.hpp> #include "User.hpp"
#include <sstream> #include <sstream>
namespace telebotxx { namespace telebotxx {
User::User() User::User() : id_(-1)
: id_(-1)
{ {
} }
@ -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);
} }
@ -65,4 +65,4 @@ std::ostream& operator<<(std::ostream& os, const User& user)
return os; return os;
} }
} } // namespace telebotxx

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