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
build-tests
cmake_install.cmake
CMakeCache.txt
CMakeFiles
doc/html
lib
Makefile
tests/telebotxx-test
.idea
build*
cmake-build-*
tests/config.json

3
.gitmodules vendored
View file

@ -4,3 +4,6 @@
[submodule "ext/rapidjson"]
path = ext/rapidjson
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
dist: trusty
dist: bionic
language: cpp
matrix:
include:
- compiler: gcc
addons:
apt:
sources:
- sourceline: 'ppa:kzemek/boost'
- ubuntu-toolchain-r-test
packages:
- g++-4.9
env: COMPILER=g++-4.9
env: COMPILER=g++
- compiler: clang
addons:
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: COMPILER=clang++
env:
global:
- TELEBOTXX_BUILD_TESTS=ON
- TELEBOTXX_GENERATE_DOC=OFF
install:
# Install CMake 3.15.0
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- 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:
- 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
- mkdir build
- cd build
- cmake ..
- cmake -DCMAKE_BUILD_TYPE=Release -DTELEBOTXX_BUILD_TESTS=ON -DTELEBOTXX_GENERATE_DOC=OFF ..
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)
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()
project(telebotxx CXX)
option (TELEBOTXX_BUILD_TESTS "Build unit tests using Boost.Test" ON)
option (TELEBOTXX_GENERATE_DOC "Generate API documentation with Doxygen" ON)
option(TELEBOTXX_USE_LIBCXX "Use LLVM libc++ as C++ standard library" OFF)
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(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
# Build and include 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")
if (TELEBOTXX_USE_LIBCXX)
if (UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
link_libraries(c++abi)
endif()
if(MSVC)
# TODO
message(WARNING "libc++ with MSVC is not yet supported")
endif()
endif()
add_subdirectory(${PROJECT_SOURCE_DIR}/ext/cpr)
include_directories(${CPR_INCLUDE_DIRS})
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin")
set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/lib")
# Include RapidJSON headers
include_directories(${PROJECT_SOURCE_DIR}/ext/rapidjson/include)
# Build dependencies
add_subdirectory(ext)
# Build library
include_directories(include)
add_subdirectory(src)
# Build tests
if(TELEBOTXX_BUILD_TESTS)
add_subdirectory(tests)
endif(TELEBOTXX_BUILD_TESTS)
add_subdirectory(tests)
endif()
# Generate docs
if(TELEBOTXX_GENERATE_DOC)
find_package(Doxygen)
if(DOXYGEN_FOUND)
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)
add_subdirectory(doc)
endif()

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,12 @@
# 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.
## Requirements
* C++14-compatible compiler
* CMake 2.8 or newer
* Boost 1.54+
* Boost Unit Test Framework (only for tests)
* C++17-compatible compiler
* CMake 3.15 or newer
## Building
*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
mkdir build
cd build
cmake ..
make
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
```
## 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
#define TELEBOTXX_ATTACHMENT_HPP
#include "Optional.hpp"
#include <string>
#include <vector>
#include <memory>
#include <boost/variant/variant.hpp>
#include <optional>
#include <string>
#include <variant>
#include <vector>
namespace telebotxx {
@ -24,14 +23,14 @@ public:
int getHeight() const;
void setHeight(int height);
const optional<int>& getFileSize() const;
void setFileSize(optional<int> fileSize);
const std::optional<int>& getFileSize() const;
void setFileSize(std::optional<int> fileSize);
private:
std::string fileId_;
int width_;
int height_;
optional<int> fileSize_;
std::optional<int> fileSize_;
};
using PhotoSizeArray = std::vector<PhotoSize>;
@ -47,25 +46,25 @@ public:
int getDuration() const;
void setDuration(int duration);
const optional<std::string>& getPerformer() const;
void setPerformer(optional<std::string> performer);
const std::optional<std::string>& getPerformer() const;
void setPerformer(std::optional<std::string> performer);
const optional<std::string>& getTitle() const;
void setTitle(optional<std::string> title);
const std::optional<std::string>& getTitle() const;
void setTitle(std::optional<std::string> title);
const optional<std::string>& getMimeType() const;
void setMimeType(optional<std::string> mimeType);
const std::optional<std::string>& getMimeType() const;
void setMimeType(std::optional<std::string> mimeType);
const optional<int>& getFileSize() const;
void setFileSize(optional<int> fileSize);
const std::optional<int>& getFileSize() const;
void setFileSize(std::optional<int> fileSize);
private:
std::string fileId_;
int duration_;
optional<std::string> performer_;
optional<std::string> title_;
optional<std::string> mimeType_;
optional<int> fileSize_;
std::optional<std::string> performer_;
std::optional<std::string> title_;
std::optional<std::string> mimeType_;
std::optional<int> fileSize_;
};
class Document
@ -76,24 +75,24 @@ public:
const std::string& getFileId() const;
void setFileId(std::string fileId);
const optional<PhotoSize>& getThumb() const;
void setThumb(optional<PhotoSize> thumb);
const std::optional<PhotoSize>& getThumb() const;
void setThumb(std::optional<PhotoSize> thumb);
const optional<std::string>& getFileName() const;
void setFileName(optional<std::string> fileName);
const std::optional<std::string>& getFileName() const;
void setFileName(std::optional<std::string> fileName);
const optional<std::string>& getMimeType() const;
void setMimeType(optional<std::string> mimeType);
const std::optional<std::string>& getMimeType() const;
void setMimeType(std::optional<std::string> mimeType);
const optional<int>& getFileSize() const;
void setFileSize(optional<int> fileSize);
const std::optional<int>& getFileSize() const;
void setFileSize(std::optional<int> fileSize);
private:
std::string fileId_;
optional<PhotoSize> thumb_;
optional<std::string> fileName_;
optional<std::string> mimeType_;
optional<int> fileSize_;
std::optional<PhotoSize> thumb_;
std::optional<std::string> fileName_;
std::optional<std::string> mimeType_;
std::optional<int> fileSize_;
};
class Sticker
@ -110,22 +109,22 @@ public:
int getHeight() const;
void setHeight(int height);
const optional<PhotoSize>& getThumb() const;
void setThumb(optional<PhotoSize> thumb);
const std::optional<PhotoSize>& getThumb() const;
void setThumb(std::optional<PhotoSize> thumb);
const optional<std::string>& getEmoji() const;
void setEmoji(optional<std::string> emoji);
const std::optional<std::string>& getEmoji() const;
void setEmoji(std::optional<std::string> emoji);
const optional<int>& getFileSize() const;
void setFileSize(optional<int> fileSize);
const std::optional<int>& getFileSize() const;
void setFileSize(std::optional<int> fileSize);
private:
std::string fileId_;
int width_;
int height_;
optional<PhotoSize> thumb_;
optional<std::string> emoji_;
optional<int> fileSize_;
std::optional<PhotoSize> thumb_;
std::optional<std::string> emoji_;
std::optional<int> fileSize_;
};
class Attachment
@ -159,9 +158,9 @@ public:
private:
Type type_;
boost::variant<PhotoSizeArray, Audio, Document, Sticker> value_;
std::variant<PhotoSizeArray, Audio, Document, Sticker> value_;
};
}
} // namespace telebotxx
#endif // TELEBOTXX_ATTACHMENT_HPP

View file

@ -1,14 +1,14 @@
#ifndef TELEBOTXX_BOTAPI_HPP
#define TELEBOTXX_BOTAPI_HPP
#include "User.hpp"
#include "Message.hpp"
#include "Update.hpp"
#include "SendMessageRequest.hpp"
#include "SendPhotoRequest.hpp"
#include "Update.hpp"
#include "User.hpp"
#include <string>
#include <memory>
#include <string>
namespace telebotxx {
@ -28,7 +28,6 @@ void setRequestOption(RequestType& request, T&& t, Ts&&... ts)
class BotApi
{
public:
/// \param [in] token bot's secret token
BotApi(const std::string& token);
@ -52,7 +51,8 @@ public:
template <typename... Ts>
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)...);
return request.execute();
}
@ -71,7 +71,8 @@ public:
template <typename... Ts>
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)...);
return request.execute();
}
@ -85,12 +86,12 @@ public:
Updates getUpdates(int offset = 0, unsigned short limit = 0, unsigned timeout = 0);
private:
std::string getTelegramMainUrl() const;
[[nodiscard]] std::string getTelegramMainUrl() const;
class Impl;
std::unique_ptr<Impl> impl_;
};
}
} // namespace telebotxx
#endif // TELEBOTXX_BOTAPI_HPP

View file

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

View file

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

View file

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

View file

@ -1,15 +1,14 @@
#ifndef TELEBOTXX_MESSAGE_HPP
#define TELEBOTXX_MESSAGE_HPP
#include "User.hpp"
#include "Chat.hpp"
#include "Attachment.hpp"
#include "Optional.hpp"
#include "Chat.hpp"
#include "User.hpp"
#include <vector>
#include <ctime>
#include <memory>
#include <boost/variant/variant.hpp>
#include <optional>
#include <vector>
namespace telebotxx {
@ -42,18 +41,18 @@ public:
size_t getLength() const;
void setLength(size_t length);
const optional<std::string>& getUrl() const;
const std::optional<std::string>& getUrl() const;
void setUrl(std::string url);
const optional<User>& getUser() const;
const std::optional<User>& getUser() const;
void setUser(User user);
private:
Type type_;
int offset_;
std::size_t length_;
optional<std::string> url_;
optional<User> user_;
std::optional<std::string> url_;
std::optional<User> user_;
};
MessageEntity::Type messageEntityTypeFromString(const std::string& str);
@ -71,8 +70,8 @@ public:
int getId() const;
void setId(int id);
const optional<User>& getFrom() const;
void setFrom(optional<User> from);
const std::optional<User>& getFrom() const;
void setFrom(std::optional<User> from);
time_t getDate() const;
void setDate(time_t date);
@ -80,44 +79,44 @@ public:
const Chat& getChat() const;
void setChat(Chat chat);
const optional<User>& getForwardFrom() const;
void setForwardFrom(optional<User> forwardFrom);
const std::optional<User>& getForwardFrom() const;
void setForwardFrom(std::optional<User> forwardFrom);
const optional<Chat>& getForwardFromChat() const;
void setForwardFromChat(optional<Chat> forwardFromChat);
const std::optional<Chat>& getForwardFromChat() const;
void setForwardFromChat(std::optional<Chat> forwardFromChat);
const optional<time_t>& getForwardDate() const;
void setForwardDate(optional<time_t> forwardDate);
const std::optional<time_t>& getForwardDate() const;
void setForwardDate(std::optional<time_t> forwardDate);
MessagePtr getReplyToMessage() const;
void setReplyToMessage(MessagePtr replyToMessage);
const optional<time_t>& getEditDate() const;
void setEditDate(optional<time_t> editDate);
const std::optional<time_t>& getEditDate() const;
void setEditDate(std::optional<time_t> editDate);
const optional<std::string>& getText() const;
void setText(optional<std::string> text);
const std::optional<std::string>& getText() const;
void setText(std::optional<std::string> text);
const optional<MessageEntities>& getEntities() const;
void setEntities(optional<MessageEntities> entities);
const std::optional<MessageEntities>& getEntities() const;
void setEntities(std::optional<MessageEntities> entities);
const optional<Attachment>& getAttachment() const;
void setAttachment(optional<Attachment> attachment);
const std::optional<Attachment>& getAttachment() const;
void setAttachment(std::optional<Attachment> attachment);
const optional<std::string>& getCaption() const;
void setCaption(optional<std::string> caption);
const std::optional<std::string>& getCaption() const;
void setCaption(std::optional<std::string> caption);
const optional<User>& getNewChatMember() const;
void setNewChatMember(optional<User> newChatMember);
const std::optional<User>& getNewChatMember() const;
void setNewChatMember(std::optional<User> newChatMember);
const optional<User>& getLeftChatMember() const;
void setLeftChatMember(optional<User> leftChatMember);
const std::optional<User>& getLeftChatMember() const;
void setLeftChatMember(std::optional<User> leftChatMember);
const optional<std::string>& getNewChatTitle() const;
void setNewChatTitle(optional<std::string> newChatTitle);
const std::optional<std::string>& getNewChatTitle() const;
void setNewChatTitle(std::optional<std::string> newChatTitle);
const optional<PhotoSizeArray> getNewChatPhoto() const;
void setNewChatPhoto(optional<PhotoSizeArray> newChatPhoto);
const std::optional<PhotoSizeArray> getNewChatPhoto() const;
void setNewChatPhoto(std::optional<PhotoSizeArray> newChatPhoto);
bool isDeleteChatPhoto() const;
void setDeleteChatPhoto(bool deleteChatPhoto);
@ -131,43 +130,43 @@ public:
bool isChannelChatCreated() const;
void setChannelChatCreated(bool channelChatCreated);
const optional<std::int64_t>& getMigrateToChatId() const;
void setMigrateToChatId(optional<std::int64_t> migrateToChatId);
const std::optional<std::int64_t>& getMigrateToChatId() const;
void setMigrateToChatId(std::optional<std::int64_t> migrateToChatId);
const optional<std::int64_t>& getMigrateFromChatId() const;
void setMigrateFromChatId(optional<std::int64_t> migrateFromChatId);
const std::optional<std::int64_t>& getMigrateFromChatId() const;
void setMigrateFromChatId(std::optional<std::int64_t> migrateFromChatId);
MessagePtr getPinnedMessage() const;
void setPinnedMessage(MessagePtr pinnedMessage);
private:
int id_;
optional<User> from_;
std::optional<User> from_;
std::time_t date_;
Chat chat_;
optional<User> forwardFrom_;
optional<Chat> forwardFromChat_;
optional<int> forwardFromMessageId_;
optional<std::time_t> forwardDate_;
std::optional<User> forwardFrom_;
std::optional<Chat> forwardFromChat_;
std::optional<int> forwardFromMessageId_;
std::optional<std::time_t> forwardDate_;
MessagePtr replyToMessage_;
optional<std::time_t> editDate_;
optional<std::string> text_;
optional<MessageEntities> entities_;
optional<Attachment> attachment_;
optional<std::string> caption_;
optional<User> newChatMember_;
optional<User> leftChatMember_;
optional<std::string> newChatTitle_;
optional<PhotoSizeArray> newChatPhoto_;
std::optional<std::time_t> editDate_;
std::optional<std::string> text_;
std::optional<MessageEntities> entities_;
std::optional<Attachment> attachment_;
std::optional<std::string> caption_;
std::optional<User> newChatMember_;
std::optional<User> leftChatMember_;
std::optional<std::string> newChatTitle_;
std::optional<PhotoSizeArray> newChatPhoto_;
bool deleteChatPhoto_;
bool groupChatCreated_;
bool superGroupChatCreated_;
bool channelChatCreated_;
optional<std::int64_t> migrateToChatId_;
optional<std::int64_t> migrateFromChatId_;
std::optional<std::int64_t> migrateToChatId_;
std::optional<std::int64_t> migrateFromChatId_;
MessagePtr pinnedMessage_;
};
}
} // namespace telebotxx
#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
#include <string>
#include <variant>
#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 \
{ \
public: \
explicit Name(bool value = DEFAULT); \
bool getValue() const; \
private: \
bool 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_; \
};
#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 {
@ -32,13 +35,18 @@ public:
ChatId(int);
ChatId(const std::string&);
enum class Type { Id, Username };
enum class Type
{
Id,
Username
};
Type getType() const;
const int getId() const;
const std::string getUsername() const;
private:
Type type_;
boost::variant<int, std::string> value_;
std::variant<int, std::string> value_;
};
TELEBOTXX_DECLARE_STRING_PARAM_CLASS(Text);
@ -60,6 +68,7 @@ class ReplyTo
public:
explicit ReplyTo(int id);
int value() const;
private:
int id_;
};
@ -67,13 +76,14 @@ private:
class Buffer
{
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);
const char *data() const;
const char* data() const;
const std::size_t size() const;
const std::string filename() const;
private:
const char *data_;
const char* data_;
std::size_t size_;
std::string filename_;
};
@ -90,7 +100,13 @@ public:
explicit Photo(const File&);
explicit Photo(const Url&);
enum class Type { Id, Buffer, File, Url };
enum class Type
{
Id,
Buffer,
File,
Url
};
Type getType() const;
int getId() const;
@ -100,7 +116,7 @@ public:
private:
Type type_;
boost::variant<int, Buffer, File, Url> value_;
std::variant<int, Buffer, File, Url> value_;
};
TELEBOTXX_DECLARE_STRING_PARAM_CLASS(CallbackData)
@ -120,7 +136,13 @@ public:
InlineKeyboardButton(InlineKeyboardButton&&);
~InlineKeyboardButton();
enum class ActionType { Url, CallbackData, SwitchInlineQuery, SwitchInlineQueryCurrentChat };
enum class ActionType
{
Url,
CallbackData,
SwitchInlineQuery,
SwitchInlineQueryCurrentChat
};
ActionType getActionType() const;
const std::string& getText() const;
@ -135,7 +157,7 @@ public:
private:
ActionType actionType_;
std::string text_;
boost::variant<Url, CallbackData, SwitchInlineQuery, SwitchInlineQueryCurrentChat> value_;
std::variant<Url, CallbackData, SwitchInlineQuery, SwitchInlineQueryCurrentChat> value_;
// \todo CallbackGame
};
@ -154,7 +176,6 @@ private:
class ReplyKeyboardMarkup
{
};
class ReplyMarkup
@ -166,7 +187,13 @@ public:
ReplyMarkup(ReplyMarkup&&);
~ReplyMarkup();
enum class Type { InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply };
enum class Type
{
InlineKeyboardMarkup,
ReplyKeyboardMarkup,
ReplyKeyboardRemove,
ForceReply
};
Type getType() const;
const InlineKeyboardMarkup& getInlineKeyboardMarkup() const;
@ -176,9 +203,9 @@ public:
private:
Type type_;
boost::variant<InlineKeyboardMarkup, ReplyKeyboardMarkup> value_;
std::variant<InlineKeyboardMarkup, ReplyKeyboardMarkup> value_;
};
}
} // namespace telebotxx
#endif // TELEBOTXX_REQUEST_OPTIONS_HPP

View file

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

View file

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

View file

@ -3,8 +3,9 @@
#include "Message.hpp"
#include <vector>
#include <memory>
#include <variant>
#include <vector>
namespace telebotxx {
@ -31,11 +32,11 @@ public:
private:
int id_;
Type type_;
boost::variant<MessagePtr> value_;
std::variant<MessagePtr> value_;
};
using Updates = std::vector<Update>;
}
} // namespace telebotxx
#endif // TELEBOTXX_UPDATE_HPP

View file

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

View file

@ -1,13 +1,8 @@
#include <telebotxx/Attachment.hpp>
#include <boost/variant.hpp>
namespace telebotxx {
PhotoSize::PhotoSize()
: width_(-1),
height_(-1),
fileSize_(-1)
PhotoSize::PhotoSize() : width_(-1), height_(-1), fileSize_(-1)
{
}
@ -41,21 +36,19 @@ void PhotoSize::setHeight(int height)
height_ = height;
}
const optional<int>& PhotoSize::getFileSize() const
const std::optional<int>& PhotoSize::getFileSize() const
{
return fileSize_;
}
void PhotoSize::setFileSize(optional<int> fileSize)
void PhotoSize::setFileSize(std::optional<int> fileSize)
{
fileSize_ = fileSize;
}
////////////////////////////////////////////////////////////////
Audio::Audio()
: duration_(-1),
fileSize_(-1)
Audio::Audio() : duration_(-1), fileSize_(-1)
{
}
@ -79,50 +72,49 @@ void Audio::setDuration(int duration)
duration_ = duration;
}
const optional<std::string>& Audio::getPerformer() const
const std::optional<std::string>& Audio::getPerformer() const
{
return performer_;
}
void Audio::setPerformer(optional<std::string> performer)
void Audio::setPerformer(std::optional<std::string> performer)
{
performer_ = std::move(performer);
}
const optional<std::string>& Audio::getTitle() const
const std::optional<std::string>& Audio::getTitle() const
{
return title_;
}
void Audio::setTitle(optional<std::string> title)
void Audio::setTitle(std::optional<std::string> title)
{
title_ = title;
}
const optional<std::string>& Audio::getMimeType() const
const std::optional<std::string>& Audio::getMimeType() const
{
return mimeType_;
}
void Audio::setMimeType(optional<std::string> mimeType)
void Audio::setMimeType(std::optional<std::string> mimeType)
{
mimeType_ = mimeType;
}
const optional<int>& Audio::getFileSize() const
const std::optional<int>& Audio::getFileSize() const
{
return fileSize_;
}
void Audio::setFileSize(optional<int> fileSize)
void Audio::setFileSize(std::optional<int> fileSize)
{
fileSize_ = fileSize;
}
////////////////////////////////////////////////////////////////
Document::Document()
: fileSize_(-1)
Document::Document() : fileSize_(-1)
{
}
@ -136,50 +128,49 @@ void Document::setFileId(std::string fileId)
fileId_ = fileId;
}
const optional<PhotoSize>& Document::getThumb() const
const std::optional<PhotoSize>& Document::getThumb() const
{
return thumb_;
}
void Document::setThumb(optional<PhotoSize> thumb)
void Document::setThumb(std::optional<PhotoSize> thumb)
{
thumb_ = thumb;
}
const optional<std::string>& Document::getFileName() const
const std::optional<std::string>& Document::getFileName() const
{
return fileName_;
}
void Document::setFileName(optional<std::string> fileName)
void Document::setFileName(std::optional<std::string> fileName)
{
fileName_ = fileName;
}
const optional<std::string>& Document::getMimeType() const
const std::optional<std::string>& Document::getMimeType() const
{
return mimeType_;
}
void Document::setMimeType(optional<std::string> mimeType)
void Document::setMimeType(std::optional<std::string> mimeType)
{
mimeType_ = mimeType;
}
const optional<int>& Document::getFileSize() const
const std::optional<int>& Document::getFileSize() const
{
return fileSize_;
}
void Document::setFileSize(optional<int> fileSize)
void Document::setFileSize(std::optional<int> fileSize)
{
fileSize_ = fileSize;
}
////////////////////////////////////////////////////////////////
Sticker::Sticker()
: fileSize_(-1)
Sticker::Sticker() : fileSize_(-1)
{
}
@ -213,32 +204,32 @@ void Sticker::setHeight(int height)
height_ = height;
}
const optional<PhotoSize>& Sticker::getThumb() const
const std::optional<PhotoSize>& Sticker::getThumb() const
{
return thumb_;
}
void Sticker::setThumb(optional<PhotoSize> thumb)
void Sticker::setThumb(std::optional<PhotoSize> thumb)
{
thumb_ = thumb;
}
const optional<std::string>& Sticker::getEmoji() const
const std::optional<std::string>& Sticker::getEmoji() const
{
return emoji_;
}
void Sticker::setEmoji(optional<std::string> emoji)
void Sticker::setEmoji(std::optional<std::string> emoji)
{
emoji_ = emoji;
}
const optional<int>& Sticker::getFileSize() const
const std::optional<int>& Sticker::getFileSize() const
{
return fileSize_;
}
void Sticker::setFileSize(optional<int> fileSize)
void Sticker::setFileSize(std::optional<int> fileSize)
{
fileSize_ = fileSize;
}
@ -246,22 +237,19 @@ void Sticker::setFileSize(optional<int> fileSize)
////////////////////////////////////////////////////////////////
Attachment::Attachment(PhotoSizeArray photos)
: type_(Type::PhotoSizeArray), value_(std::move(photos))
: type_(Type::PhotoSizeArray), value_(std::move(photos))
{
}
Attachment::Attachment(Audio audio)
: type_(Type::Audio), value_(std::move(audio))
Attachment::Attachment(Audio audio) : type_(Type::Audio), value_(std::move(audio))
{
}
Attachment::Attachment(Document document)
: type_(Type::Document), value_(std::move(document))
Attachment::Attachment(Document document) : type_(Type::Document), value_(std::move(document))
{
}
Attachment::Attachment(Sticker sticker)
: type_(Type::Sticker), value_(std::move(sticker))
Attachment::Attachment(Sticker sticker) : type_(Type::Sticker), value_(std::move(sticker))
{
}
@ -272,22 +260,24 @@ Attachment::Type Attachment::getType() const
const PhotoSizeArray& Attachment::getPhotoSizeArray() const
{
return boost::get<PhotoSizeArray>(value_);
return std::get<PhotoSizeArray>(value_);
}
const Audio& Attachment::getAudio() const
{
return boost::get<Audio>(value_);;
return std::get<Audio>(value_);
;
}
const Document& Attachment::getDocument() const
{
return boost::get<Document>(value_);
return std::get<Document>(value_);
}
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 <telebotxx/Exception.hpp>
#include <telebotxx/Logging.hpp>
#include "BotApi.hpp"
#include "Exception.hpp"
#include "JsonObjects.hpp"
#include "Logging.hpp"
#include <cpr/cpr.h>
#include <rapidjson/writer.h>
#include <iostream>
#include <sstream>
#include <rapidjson/writer.h>
#include <cpr/cpr.h>
namespace telebotxx {
class BotApi::Impl
{
public:
Impl(const std::string& token)
: token_(token)
Impl(const std::string& token) : token_(token)
{
telegramMainUrl_ = "https://api.telegram.org/bot" + token_;
botUser_ = getMe();
@ -37,14 +36,12 @@ public:
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"},
cpr::Multipart{{"chat_id", chat},
{"photo", cpr::File{filename}},
{"caption", caption}
}
);
auto r = cpr::Post(
cpr::Url{telegramMainUrl_ + "/sendPhoto"},
cpr::Multipart{{"chat_id", chat}, {"photo", cpr::File{filename}}, {"caption", caption}});
auto& response = r.text;
if (debugMode)
@ -58,7 +55,8 @@ public:
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
using namespace rapidjson;
@ -77,9 +75,7 @@ public:
std::string request = s.GetString();
auto r = cpr::Post(cpr::Url{telegramMainUrl_ + "/sendPhoto"},
cpr::Header{{"Content-Type", "application/json"}},
cpr::Body{request}
);
cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{request});
auto& response = r.text;
if (debugMode)
@ -121,9 +117,7 @@ public:
std::string request = s.GetString();
auto r = cpr::Post(cpr::Url{telegramMainUrl_ + "/getUpdates"},
cpr::Header{{"Content-Type", "application/json"}},
cpr::Body{request}
);
cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{request});
auto& response = r.text;
if (debugMode)
@ -136,20 +130,15 @@ public:
return parseUpdates(doc, "result");
}
std::string getTelegramMainUrl() const
{
return telegramMainUrl_;
}
std::string getTelegramMainUrl() const { return telegramMainUrl_; }
private:
std::string token_;
std::string telegramMainUrl_;
User botUser_;
};
BotApi::BotApi(const std::string& token)
: impl_(std::make_unique<Impl>(token))
BotApi::BotApi(const std::string& token) : impl_(std::make_unique<Impl>(token))
{
}
@ -162,13 +151,15 @@ User BotApi::getMe()
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();
}
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();
}
@ -182,4 +173,4 @@ std::string BotApi::getTelegramMainUrl() const
return impl_->getTelegramMainUrl();
}
}
} // namespace telebotxx

View file

@ -1,13 +1,5 @@
cmake_minimum_required(VERSION 2.8)
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
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
@ -26,6 +18,12 @@ set(SOURCE_FILES Attachment.cpp
)
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")

View file

@ -1,12 +1,10 @@
#include <telebotxx/Chat.hpp>
#include "Chat.hpp"
#include <stdexcept>
namespace telebotxx {
Chat::Chat()
: id_(-1),
type_(Type::Private),
allAdmins_(false)
Chat::Chat() : id_(-1), type_(Type::Private), allAdmins_(false)
{
}
@ -30,42 +28,42 @@ void Chat::setType(Chat::Type type)
type_ = type;
}
const optional<std::string>& Chat::getTitle() const
const std::optional<std::string>& Chat::getTitle() const
{
return title_;
}
void Chat::setTitle(optional<std::string> title)
void Chat::setTitle(std::optional<std::string> title)
{
title_ = title;
}
const optional<std::string>& Chat::getUsername() const
const std::optional<std::string>& Chat::getUsername() const
{
return username_;
}
void Chat::setUsername(optional<std::string> username)
void Chat::setUsername(std::optional<std::string> username)
{
username_ = username;
}
const optional<std::string>& Chat::getFirstName() const
const std::optional<std::string>& Chat::getFirstName() const
{
return firstName_;
}
void Chat::setFirstName(optional<std::string> firstName)
void Chat::setFirstName(std::optional<std::string> firstName)
{
firstName_ = firstName;
}
const optional<std::string>& Chat::getLastName() const
const std::optional<std::string>& Chat::getLastName() const
{
return lastName_;
}
void Chat::setLastName(optional<std::string> lastName)
void Chat::setLastName(std::optional<std::string> lastName)
{
lastName_ = lastName;
}
@ -94,4 +92,4 @@ Chat::Type chatTypeFromString(const std::string& str)
throw std::invalid_argument("Unknown chat type");
}
}
} // namespace telebotxx

View file

@ -4,17 +4,49 @@
namespace telebotxx {
namespace impl {
template<> bool is<int>(const rapidjson::Value& obj) { return obj.IsInt(); }
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(); }
template <>
bool is<int>(const rapidjson::Value& obj)
{
return obj.IsInt();
}
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)
{
@ -24,7 +56,8 @@ bool check(const rapidjson::Value& obj, const char* name)
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))
{
@ -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))
{
@ -67,9 +101,9 @@ const rapidjson::Value& parseArray(const rapidjson::Value& parent, const char* n
}
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;
auto& obj = parseObject(parent, name, required, found);
if (found)
@ -87,9 +121,9 @@ optional<Chat> parse<Chat>(const rapidjson::Value& parent, const char* name, boo
}
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;
auto& obj = parseObject(parent, name, required, found);
if (found)
@ -113,9 +147,10 @@ PhotoSize parsePhotoSize(const rapidjson::Value& obj)
}
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;
auto& obj = parseObject(parent, name, required, found);
if (found)
@ -126,9 +161,10 @@ optional<PhotoSize> parse<PhotoSize>(const rapidjson::Value& parent, const char*
}
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;
auto& obj = parseArray(parent, name, required, found);
if (found)
@ -142,9 +178,9 @@ optional<PhotoSizeArray> parse<PhotoSizeArray>(const rapidjson::Value& parent, c
}
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;
auto& obj = parseObject(parent, name, required, found);
if (found)
@ -160,9 +196,9 @@ optional<Audio> parse<Audio>(const rapidjson::Value& parent, const char* name, b
}
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;
auto& obj = parseObject(parent, name, required, found);
if (found)
@ -178,9 +214,9 @@ optional<Document> parse<Document>(const rapidjson::Value& parent, const char* n
}
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;
auto& obj = parseObject(parent, name, required, found);
if (found)
@ -197,9 +233,10 @@ optional<Sticker> parse<Sticker>(const rapidjson::Value& parent, const char* nam
}
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"))
attachment.emplace(std::move(*photo));
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->setEditDate(allow<std::int64_t>(obj, "edit_date"));
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->setCaption(allow<std::string>(obj, "caption"));
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
#define TELEBOTXX_JSON_OBJECTS_HPP
#include <telebotxx/Attachment.hpp>
#include <telebotxx/Message.hpp>
#include <telebotxx/Update.hpp>
#include <telebotxx/User.hpp>
#include <telebotxx/Optional.hpp>
#include <telebotxx/Exception.hpp>
#include <memory>
#include "Attachment.hpp"
#include "Exception.hpp"
#include "Message.hpp"
#include "Update.hpp"
#include "User.hpp"
#include <rapidjson/document.h>
#include <memory>
#include <optional>
namespace telebotxx {
const bool REQUIRED = true;
@ -19,22 +19,32 @@ const bool OPTIONAL = false;
namespace impl {
template<typename T> bool is(const rapidjson::Value& obj);
template<> bool is<int>(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>
bool is(const rapidjson::Value& obj);
template <>
bool is<int>(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<> const int 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);
template <typename T>
const T get(const rapidjson::Value& obj);
template <>
const int 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>
optional<T> parse(const rapidjson::Value& obj, const char* name, bool required)
template <typename T>
std::optional<T> parse(const rapidjson::Value& obj, const char* name, bool required)
{
if (obj.HasMember(name))
{
@ -46,7 +56,7 @@ optional<T> parse(const rapidjson::Value& obj, const char* name, bool required)
else if (required)
throw ParseError(std::string("Field '") + name + "' not found");
else
return boost::none;
return std::nullopt;
}
template <typename T>
@ -56,7 +66,7 @@ T require(const rapidjson::Value& obj, const char* name)
}
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);
}
@ -68,7 +78,8 @@ bool check(const rapidjson::Value& obj, const char* name);
/// \param name field with Document object
/// \param required REQUIRED or OPTIONAL
/// \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
/// \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
void checkResponse(const rapidjson::Document& doc);
}
} // namespace telebotxx
#endif // TELEBOTXX_JSON_OBJECTS_HPP

View file

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

View file

@ -1,11 +1,10 @@
#include <telebotxx/Message.hpp>
#include "Message.hpp"
#include <stdexcept>
namespace telebotxx {
MessageEntity::MessageEntity()
: type_(Type::Mention),
offset_(-1),
length_(0)
MessageEntity::MessageEntity() : type_(Type::Mention), offset_(-1), length_(0)
{
}
@ -39,7 +38,7 @@ void MessageEntity::setLength(size_t length)
length_ = length;
}
const optional<std::string>& MessageEntity::getUrl() const
const std::optional<std::string>& MessageEntity::getUrl() const
{
return url_;
}
@ -49,7 +48,7 @@ void MessageEntity::setUrl(std::string url)
url_ = std::move(url);
}
const optional<User>& MessageEntity::getUser() const
const std::optional<User>& MessageEntity::getUser() const
{
return user_;
}
@ -90,11 +89,11 @@ MessageEntity::Type messageEntityTypeFromString(const std::string& str)
////////////////////////////////////////////////////////////////
Message::Message()
: id_(-1),
deleteChatPhoto_(false),
groupChatCreated_(false),
superGroupChatCreated_(false),
channelChatCreated_(false)
: id_(-1),
deleteChatPhoto_(false),
groupChatCreated_(false),
superGroupChatCreated_(false),
channelChatCreated_(false)
{
}
@ -108,12 +107,12 @@ void Message::setId(int id)
id_ = id;
}
const boost::optional<User>& Message::getFrom() const
const std::optional<User>& Message::getFrom() const
{
return from_;
}
void Message::setFrom(optional<User> from)
void Message::setFrom(std::optional<User> from)
{
from_ = std::move(from);
}
@ -138,32 +137,32 @@ void Message::setChat(Chat chat)
chat_ = std::move(chat);
}
const optional<User>& Message::getForwardFrom() const
const std::optional<User>& Message::getForwardFrom() const
{
return forwardFrom_;
}
void Message::setForwardFrom(optional<User> forwardFrom)
void Message::setForwardFrom(std::optional<User> forwardFrom)
{
forwardFrom_ = std::move(forwardFrom);
}
const optional<Chat>& Message::getForwardFromChat() const
const std::optional<Chat>& Message::getForwardFromChat() const
{
return forwardFromChat_;
}
void Message::setForwardFromChat(optional<Chat> forwardFromChat)
void Message::setForwardFromChat(std::optional<Chat> forwardFromChat)
{
forwardFromChat_ = std::move(forwardFromChat);
}
const optional<time_t>& Message::getForwardDate() const
const std::optional<time_t>& Message::getForwardDate() const
{
return forwardDate_;
}
void Message::setForwardDate(optional<time_t> forwardDate)
void Message::setForwardDate(std::optional<time_t> forwardDate)
{
forwardDate_ = forwardDate;
}
@ -178,92 +177,92 @@ void Message::setReplyToMessage(MessagePtr replyToMessage)
replyToMessage_ = replyToMessage;
}
const optional<time_t>& Message::getEditDate() const
const std::optional<time_t>& Message::getEditDate() const
{
return editDate_;
}
void Message::setEditDate(optional<time_t> editDate)
void Message::setEditDate(std::optional<time_t> editDate)
{
editDate_ = editDate;
}
const optional<std::string>& Message::getText() const
const std::optional<std::string>& Message::getText() const
{
return text_;
}
void Message::setText(optional<std::string> text)
void Message::setText(std::optional<std::string> text)
{
text_ = std::move(text);
}
const optional<MessageEntities>& Message::getEntities() const
const std::optional<MessageEntities>& Message::getEntities() const
{
return entities_;
}
void Message::setEntities(optional<MessageEntities> entities)
void Message::setEntities(std::optional<MessageEntities> entities)
{
entities_ = std::move(entities);
}
const optional<Attachment>& Message::getAttachment() const
const std::optional<Attachment>& Message::getAttachment() const
{
return attachment_;
}
void Message::setAttachment(optional<Attachment> attachment)
void Message::setAttachment(std::optional<Attachment> attachment)
{
attachment_ = std::move(attachment);
}
const optional<std::string>& Message::getCaption() const
const std::optional<std::string>& Message::getCaption() const
{
return caption_;
}
void Message::setCaption(optional<std::string> caption)
void Message::setCaption(std::optional<std::string> caption)
{
caption_ = std::move(caption);
}
const optional<User>& Message::getNewChatMember() const
const std::optional<User>& Message::getNewChatMember() const
{
return newChatMember_;
}
void Message::setNewChatMember(optional<User> newChatMember)
void Message::setNewChatMember(std::optional<User> newChatMember)
{
newChatMember_ = std::move(newChatMember);
}
const optional<User>& Message::getLeftChatMember() const
const std::optional<User>& Message::getLeftChatMember() const
{
return leftChatMember_;
}
void Message::setLeftChatMember(optional<User> leftChatMember)
void Message::setLeftChatMember(std::optional<User> leftChatMember)
{
leftChatMember_ = std::move(leftChatMember);
}
const optional<std::string>& Message::getNewChatTitle() const
const std::optional<std::string>& Message::getNewChatTitle() const
{
return newChatTitle_;
}
void Message::setNewChatTitle(optional<std::string> newChatTitle)
void Message::setNewChatTitle(std::optional<std::string> newChatTitle)
{
newChatTitle_ = std::move(newChatTitle);
}
const optional<PhotoSizeArray> Message::getNewChatPhoto() const
const std::optional<PhotoSizeArray> Message::getNewChatPhoto() const
{
return newChatPhoto_;
}
void Message::setNewChatPhoto(optional<PhotoSizeArray> newChatPhoto)
void Message::setNewChatPhoto(std::optional<PhotoSizeArray> newChatPhoto)
{
newChatPhoto_ = std::move(newChatPhoto);
}
@ -308,22 +307,22 @@ void Message::setChannelChatCreated(bool channelChatCreated)
channelChatCreated_ = channelChatCreated;
}
const optional<std::int64_t>& Message::getMigrateToChatId() const
const std::optional<std::int64_t>& Message::getMigrateToChatId() const
{
return migrateToChatId_;
}
void Message::setMigrateToChatId(optional<std::int64_t> migrateToChatId)
void Message::setMigrateToChatId(std::optional<std::int64_t> migrateToChatId)
{
migrateToChatId_ = migrateToChatId;
}
const optional<std::int64_t>& Message::getMigrateFromChatId() const
const std::optional<std::int64_t>& Message::getMigrateFromChatId() const
{
return migrateFromChatId_;
}
void Message::setMigrateFromChatId(optional<std::int64_t> migrateFromChatId)
void Message::setMigrateFromChatId(std::optional<std::int64_t> migrateFromChatId)
{
migrateFromChatId_ = migrateFromChatId;
}
@ -338,4 +337,4 @@ void Message::setPinnedMessage(MessagePtr pinnedMessage)
pinnedMessage_ = pinnedMessage;
}
}
} // namespace telebotxx

View file

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

View file

@ -1,7 +1,7 @@
#ifndef TELEBOTXX_REPLY_MARKUP_HPP
#define TELEBOTXX_REPLY_MARKUP_HPP
#include <telebotxx/RequestOptions.hpp>
#include "RequestOptions.hpp"
#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) { } \
bool 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_; }
#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 {
ChatId::ChatId(int id)
: type_(Type::Id), value_(id)
ChatId::ChatId(int id) : type_(Type::Id), value_(id)
{
}
ChatId::ChatId(const std::string& str)
: type_(Type::Username), value_(str)
ChatId::ChatId(const std::string& str) : type_(Type::Username), value_(str)
{
}
@ -27,12 +25,12 @@ ChatId::Type ChatId::getType() const
const int ChatId::getId() const
{
return boost::get<int>(value_);
return std::get<int>(value_);
}
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)
: id_(id)
ReplyTo::ReplyTo(int id) : id_(id)
{
}
@ -66,12 +63,12 @@ int ReplyTo::value() const
////////////////////////////////////////////////////////////////
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)
: 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)
: type_(Type::Id), value_(id)
Photo::Photo(int id) : type_(Type::Id), value_(id)
{
}
Photo::Photo(const Buffer& buffer)
: type_(Type::Buffer), value_(buffer)
Photo::Photo(const Buffer& buffer) : type_(Type::Buffer), value_(buffer)
{
}
Photo::Photo(const File& file)
: type_(Type::File), value_(file)
Photo::Photo(const File& file) : type_(Type::File), value_(file)
{
}
Photo::Photo(const Url& url)
: type_(Type::Url), value_(url)
Photo::Photo(const Url& url) : type_(Type::Url), value_(url)
{
}
@ -127,22 +120,22 @@ Photo::Type Photo::getType() const
int Photo::getId() const
{
return boost::get<int>(value_);
return std::get<int>(value_);
}
const Buffer& Photo::getBuffer() const
{
return boost::get<Buffer>(value_);
return std::get<Buffer>(value_);
}
const File& Photo::getFile() const
{
return boost::get<File>(value_);
return std::get<File>(value_);
}
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)
: actionType_(ActionType::Url), text_(text), value_(url)
: actionType_(ActionType::Url), text_(text), value_(url)
{
}
InlineKeyboardButton::InlineKeyboardButton(const std::string& text, const CallbackData& callbackData)
: actionType_(ActionType::CallbackData), text_(text), value_(callbackData)
{
}
InlineKeyboardButton::InlineKeyboardButton(const std::string& text, const SwitchInlineQuery& switchInlineQuery)
: actionType_(ActionType::SwitchInlineQuery), text_(text), value_(switchInlineQuery)
: actionType_(ActionType::CallbackData), text_(text), value_(callbackData)
{
}
InlineKeyboardButton::InlineKeyboardButton(const std::string& text,
const SwitchInlineQueryCurrentChat& switchInlineQueryCurrentChat)
: actionType_(ActionType::SwitchInlineQueryCurrentChat), text_(text), value_(switchInlineQueryCurrentChat)
const SwitchInlineQuery& switchInlineQuery)
: 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
{
return boost::get<Url>(value_);;
return std::get<Url>(value_);
}
const CallbackData& InlineKeyboardButton::getCallbackData() const
{
return boost::get<CallbackData>(value_);
return std::get<CallbackData>(value_);
}
const SwitchInlineQuery& InlineKeyboardButton::getSwitchInlineQuery() const
{
return boost::get<SwitchInlineQuery>(value_);
return std::get<SwitchInlineQuery>(value_);
}
const SwitchInlineQueryCurrentChat& InlineKeyboardButton::getSwitchInlineQueryCurrentChat() const
{
return boost::get<SwitchInlineQueryCurrentChat>(value_);
return std::get<SwitchInlineQueryCurrentChat>(value_);
}
void InlineKeyboardButton::swap(InlineKeyboardButton& other)
@ -245,12 +241,12 @@ const std::vector<InlineKeyboardButtonRow>& InlineKeyboardMarkup::getRows() cons
////////////////////////////////////////////////////////////////
ReplyMarkup::ReplyMarkup(const InlineKeyboardMarkup& keyboard)
: type_(Type::InlineKeyboardMarkup), value_(keyboard)
: type_(Type::InlineKeyboardMarkup), value_(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
{
return boost::get<InlineKeyboardMarkup>(value_);
return std::get<InlineKeyboardMarkup>(value_);
}
void ReplyMarkup::swap(ReplyMarkup& other)
@ -281,4 +277,4 @@ const ReplyMarkup& ReplyMarkup::operator=(ReplyMarkup other)
return *this;
}
}
} // namespace telebotxx

View file

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

View file

@ -1,6 +1,7 @@
#include <telebotxx/SendPhotoRequest.hpp>
#include <telebotxx/Logging.hpp>
#include "SendPhotoRequest.hpp"
#include "JsonObjects.hpp"
#include "Logging.hpp"
#include "ReplyMarkup.hpp"
#include <cpr/cpr.h>
@ -8,7 +9,7 @@
#include <rapidjson/writer.h>
#include <iostream>
#include <boost/optional.hpp>
#include <optional>
namespace telebotxx {
@ -16,14 +17,11 @@ class SendPhotoRequest::Impl
{
public:
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)
{
caption_ = caption;
}
void setCaption(const Caption& caption) { caption_ = caption; }
void setDisableNotification(const DisableNotification& disableNotification)
{
@ -35,10 +33,7 @@ public:
replyToMessageId_ = replyToMessageId;
}
void setReplyMarkup(const ReplyMarkup& replyMarkup)
{
replyMarkup_ = replyMarkup;
}
void setReplyMarkup(const ReplyMarkup& replyMarkup) { replyMarkup_ = replyMarkup; }
Message execute()
{
@ -57,8 +52,8 @@ public:
{
const char* data = photo_.getBuffer().data();
std::size_t size = photo_.getBuffer().size();
const std::string filename = photo_.getBuffer().filename();
multipart.parts.push_back({"photo", cpr::Buffer(data, data + size, filename)});
std::string filename = photo_.getBuffer().filename();
multipart.parts.push_back({"photo", cpr::Buffer(data, data + size, std::move(filename))});
}
else if (photo_.getType() == Photo::Type::File)
multipart.parts.push_back({"photo", cpr::File(photo_.getFile().getValue())});
@ -106,14 +101,16 @@ private:
std::string telegramMainUrl_;
ChatId chatId_;
Photo photo_;
boost::optional<Caption> caption_;
boost::optional<DisableNotification> disableNotification_;
boost::optional<ReplyTo> replyToMessageId_;
boost::optional<ReplyMarkup> replyMarkup_;
std::optional<Caption> caption_;
std::optional<DisableNotification> disableNotification_;
std::optional<ReplyTo> replyToMessageId_;
std::optional<ReplyMarkup> replyMarkup_;
};
SendPhotoRequest::SendPhotoRequest(const std::string& telegramMainUrl, const ChatId& chat, const Photo& photo)
: impl_(std::make_unique<Impl>(telegramMainUrl, chat, photo))
SendPhotoRequest::SendPhotoRequest(const std::string& telegramMainUrl,
const ChatId& chat,
const Photo& photo)
: impl_(std::make_unique<Impl>(telegramMainUrl, chat, photo))
{
}
@ -166,4 +163,4 @@ Message SendPhotoRequest::execute()
return impl_->execute();
}
}
} // namespace telebotxx

View file

@ -1,12 +1,9 @@
#include <telebotxx/Update.hpp>
#include <boost/variant.hpp>
#include "Update.hpp"
namespace telebotxx {
Update::Update(int id, Type type, std::unique_ptr<Message> message)
: id_(id),
type_(type),
value_(std::move(message))
: id_(id), type_(type), value_(std::move(message))
{
}
@ -22,7 +19,7 @@ Update::Type Update::getType() 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>
namespace telebotxx {
User::User()
: id_(-1)
User::User() : id_(-1)
{
}
@ -28,22 +28,22 @@ void User::setFirstName(std::string firstName)
firstName_ = std::move(firstName);
}
const optional<std::string>& User::getLastName() const
const std::optional<std::string>& User::getLastName() const
{
return lastName_;
}
void User::setLastName(optional<std::string> lastName)
void User::setLastName(std::optional<std::string> lastName)
{
lastName_ = std::move(lastName);
}
const optional<std::string>& User::getUsername() const
const std::optional<std::string>& User::getUsername() const
{
return username_;
}
void User::setUsername(optional<std::string> username)
void User::setUsername(std::optional<std::string> username)
{
username_ = std::move(username);
}
@ -65,4 +65,4 @@ std::ostream& operator<<(std::ostream& os, const User& user)
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")
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(SOURCE_FILES Dummy.cpp TestTypes.cpp TestApi.cpp)
set(SOURCE_FILES TestApi.cpp)
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")

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/Logging.hpp>
#include <memory>
#include <fstream>
#include <catch2/catch_all.hpp>
#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;
std::string token;
std::string chat;
std::string photoFile;
std::string photoUrl;
std::unique_ptr<BotApi> bot;
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;
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())
{
switch (update.getType())
{
case Update::Type::Message:
case Update::Type::EditedMessage:
case Update::Type::ChannelPost:
case Update::Type::EditedChannelPost:
{
auto message = update.getMessage();
if (message->getFrom())
std::cout << *message->getFrom() << ": ";
if (message->getText())
std::cout << *message->getText() << std::endl;
break;
}
}
case Update::Type::Message:
case Update::Type::EditedMessage:
case Update::Type::ChannelPost:
case Update::Type::EditedChannelPost:
{
auto message = update.getMessage();
if (message->getFrom())
std::cout << *message->getFrom() << ": ";
if (message->getText())
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()