Merge branch 'dev' into inline_keyboard

Conflicts:
	src/RequestOptions.cpp
This commit is contained in:
Kirill Kirilenko 2017-02-19 18:15:32 +03:00
commit c24136c461
23 changed files with 618 additions and 1010 deletions

View file

@ -1,5 +1,5 @@
sudo: required sudo: required
dist: precise dist: trusty
language: cpp language: cpp
matrix: matrix:
@ -8,36 +8,21 @@ matrix:
addons: addons:
apt: apt:
sources: sources:
- sourceline: 'ppa:kzemek/boost'
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
packages: packages:
- g++-4.9 - g++-4.9
env: COMPILER=g++-4.9 env: COMPILER=g++-4.9
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
env: COMPILER=g++-5
- compiler: clang - compiler: clang
addons: addons:
apt: apt:
sources: sources:
- sourceline: 'ppa:kzemek/boost'
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.6 - llvm-toolchain-precise-3.6
packages: packages:
- clang-3.6 - clang-3.6
env: COMPILER=clang++-3.6 env: COMPILER=clang++-3.6
- compiler: clang
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7
packages:
- clang-3.7
env: COMPILER=clang++-3.7
env: env:
global: global:
@ -45,7 +30,7 @@ env:
- TELEBOTXX_GENERATE_DOC=OFF - TELEBOTXX_GENERATE_DOC=OFF
before_script: before_script:
- sudo apt-get install -y libboost-test-dev libboost-system-dev libcurl4-openssl-dev - sudo apt-get install -y libboost1.58-dev libboost-test1.58-dev libboost-system1.58-dev libcurl4-openssl-dev
- export CXX=$COMPILER - export CXX=$COMPILER
- mkdir build - mkdir build
- cd build - cd build

View file

@ -1,13 +1,133 @@
#ifndef TELEBOTXX_ATTACHMENT_HPP #ifndef TELEBOTXX_ATTACHMENT_HPP
#define TELEBOTXX_ATTACHMENT_HPP #define TELEBOTXX_ATTACHMENT_HPP
#include "Optional.hpp"
#include <string> #include <string>
#include <ctime>
#include <memory>
#include <vector> #include <vector>
#include <memory>
#include <boost/variant/variant.hpp>
namespace telebotxx { namespace telebotxx {
class PhotoSize
{
public:
PhotoSize();
const std::string& getFileId() const;
void setFileId(const std::string& fileId);
int getWidth() const;
void setWidth(int width);
int getHeight() const;
void setHeight(int height);
const optional<int>& getFileSize() const;
void setFileSize(optional<int> fileSize);
private:
std::string fileId_;
int width_;
int height_;
optional<int> fileSize_;
};
using PhotoSizeArray = std::vector<PhotoSize>;
class Audio
{
public:
Audio();
const std::string& getFileId() const;
void setFileId(const std::string& fileId);
int getDuration() const;
void setDuration(int duration);
const optional<std::string>& getPerformer() const;
void setPerformer(optional<std::string> performer);
const optional<std::string>& getTitle() const;
void setTitle(optional<std::string> title);
const optional<std::string>& getMimeType() const;
void setMimeType(optional<std::string> mimeType);
const optional<int>& getFileSize() const;
void setFileSize(optional<int> fileSize);
private:
std::string fileId_;
int duration_;
optional<std::string> performer_;
optional<std::string> title_;
optional<std::string> mimeType_;
optional<int> fileSize_;
};
class Document
{
public:
Document();
const std::string& getFileId() const;
void setFileId(std::string fileId);
const optional<PhotoSize>& getThumb() const;
void setThumb(optional<PhotoSize> thumb);
const optional<std::string>& getFileName() const;
void setFileName(optional<std::string> fileName);
const optional<std::string>& getMimeType() const;
void setMimeType(optional<std::string> mimeType);
const optional<int>& getFileSize() const;
void setFileSize(optional<int> fileSize);
private:
std::string fileId_;
optional<PhotoSize> thumb_;
optional<std::string> fileName_;
optional<std::string> mimeType_;
optional<int> fileSize_;
};
class Sticker
{
public:
Sticker();
const std::string& getFileId() const;
void setFileId(const std::string& fileId);
int getWidth() const;
void setWidth(int width);
int getHeight() const;
void setHeight(int height);
const optional<PhotoSize>& getThumb() const;
void setThumb(optional<PhotoSize> thumb);
const optional<std::string>& getEmoji() const;
void setEmoji(optional<std::string> emoji);
const optional<int>& getFileSize() const;
void setFileSize(optional<int> fileSize);
private:
std::string fileId_;
int width_;
int height_;
optional<PhotoSize> thumb_;
optional<std::string> emoji_;
optional<int> fileSize_;
};
class Attachment class Attachment
{ {
public: public:
@ -25,194 +145,23 @@ public:
Venue Venue
}; };
Attachment(Type type); Attachment(PhotoSizeArray);
Attachment(const Attachment&); Attachment(Audio);
Attachment(Attachment&&); Attachment(Document);
virtual ~Attachment() = 0; Attachment(Sticker);
Type getType() const; Type getType() const;
void swap(Attachment& other) noexcept; const PhotoSizeArray& getPhotoSizeArray() const;
const Audio& getAudio() const;
const Document& getDocument() const;
const Sticker& getSticker() const;
private: private:
Type attachmentType_; Type type_;
boost::variant<PhotoSizeArray, Audio, Document, Sticker> value_;
}; };
using AttachmentPtr = std::shared_ptr<Attachment>;
class PhotoSize
{
public:
PhotoSize();
PhotoSize(const PhotoSize&);
PhotoSize(PhotoSize&&);
~PhotoSize();
const std::string& getFileId() const;
void setFileId(const std::string& fileId);
int getWidth() const;
void setWidth(int width);
int getHeight() const;
void setHeight(int height);
int getFileSize() const;
void setFileSize(int fileSize);
void swap(PhotoSize& other) noexcept;
const PhotoSize& operator=(PhotoSize other) noexcept;
private:
std::string fileId_;
int width_;
int height_;
int fileSize_;
};
using PhotoSizePtr = std::shared_ptr<PhotoSize>;
class PhotoSizeArray : public Attachment
{
public:
PhotoSizeArray();
PhotoSizeArray(const PhotoSizeArray&);
PhotoSizeArray(PhotoSizeArray&&);
~PhotoSizeArray();
const std::vector<PhotoSize>& getArray() const;
void setArray(const std::vector<PhotoSize>& array);
void swap(PhotoSizeArray& other) noexcept;
const PhotoSizeArray& operator=(PhotoSizeArray other) noexcept;
private:
std::vector<PhotoSize> array_;
};
using PhotoSizeArrayPtr = std::shared_ptr<PhotoSizeArray>;
class Audio : public Attachment
{
public:
Audio();
Audio(const Audio&);
Audio(Audio&&);
~Audio();
const std::string& getFileId() const;
void setFileId(const std::string& fileId);
int getDuration() const;
void setDuration(int duration);
const std::string& getPerformer() const;
void setPerformer(const std::string& performer);
const std::string& getTitle() const;
void setTitle(const std::string& title);
const std::string& getMimeType() const;
void setMimeType(const std::string& mimeType);
int getFileSize() const;
void setFileSize(int fileSize);
void swap(Audio& other) noexcept;
const Audio& operator=(Audio other) noexcept;
private:
std::string fileId_;
int duration_;
std::string performer_;
std::string title_;
std::string mimeType_;
int fileSize_;
};
class Document : public Attachment
{
public:
Document();
Document(const Document&);
Document(Document&&);
~Document();
const std::string& getFileId() const;
void setFileId(const std::string& fileId);
const PhotoSizePtr getThumb() const;
void setThumb(const PhotoSizePtr& thumb);
const std::string& getFileName() const;
void setFileName(const std::string& fileName);
const std::string& getMimeType() const;
void setMimeType(const std::string& mimeType);
int getFileSize() const;
void setFileSize(int fileSize);
void swap(Document& other) noexcept;
const Document& operator=(Document other) noexcept;
private:
std::string fileId_;
PhotoSizePtr thumb_;
std::string fileName_;
std::string mimeType_;
int fileSize_;
};
class Sticker : public Attachment
{
public:
Sticker();
Sticker(const Sticker&);
Sticker(Sticker&&);
~Sticker();
const std::string& getFileId() const;
void setFileId(const std::string& fileId);
int getWidth() const;
void setWidth(int width);
int getHeight() const;
void setHeight(int height);
const PhotoSizePtr getThumb() const;
void setThumb(const PhotoSizePtr& thumb);
const std::string& getEmoji() const;
void setEmoji(const std::string& emoji);
int getFileSize() const;
void setFileSize(int fileSize);
void swap(Sticker& other) noexcept;
const Sticker& operator=(Sticker other) noexcept;
private:
std::string fileId_;
int width_;
int height_;
PhotoSizePtr thumb_;
std::string emoji_;
int fileSize_;
};
void swap(PhotoSize& lhs, PhotoSize& rhs);
void swap(PhotoSizeArray& lhs, PhotoSizeArray& rhs);
void swap(Audio& lhs, Audio& rhs);
void swap(Document& lhs, Document& rhs);
void swap(Sticker& lhs, Sticker& rhs);
} }
#endif // TELEBOTXX_ATTACHMENT_HPP #endif // TELEBOTXX_ATTACHMENT_HPP

View file

@ -81,6 +81,7 @@ public:
/// \param limit maximum number of updates to be retrieved /// \param limit maximum number of updates to be retrieved
/// \param timeout timeout in seconds for long polling /// \param timeout timeout in seconds for long polling
/// \return Updates (vector of Update) /// \return Updates (vector of Update)
/// \todo allowed_updates
Updates getUpdates(int offset = 0, unsigned short limit = 0, unsigned timeout = 0); Updates getUpdates(int offset = 0, unsigned short limit = 0, unsigned timeout = 0);
private: private:

View file

@ -1,6 +1,8 @@
#ifndef TELEBOTXX_CHAT_HPP #ifndef TELEBOTXX_CHAT_HPP
#define TELEBOTXX_CHAT_HPP #define TELEBOTXX_CHAT_HPP
#include "Optional.hpp"
#include <string> #include <string>
#include <memory> #include <memory>
#include <cstdint> #include <cstdint>
@ -19,9 +21,6 @@ public:
}; };
Chat(); Chat();
Chat(const Chat&);
Chat(Chat&&);
~Chat();
std::int64_t getId() const; std::int64_t getId() const;
void setId(std::int64_t id); void setId(std::int64_t id);
@ -29,39 +28,31 @@ public:
Type getType() const; Type getType() const;
void setType(Type type); void setType(Type type);
const std::string& getTitle() const; const optional<std::string>& getTitle() const;
void setTitle(const std::string& title); void setTitle(optional<std::string> title);
const std::string& getUsername() const; const optional<std::string>& getUsername() const;
void setUsername(const std::string& username); void setUsername(optional<std::string> username);
const std::string& getFirstName() const; const optional<std::string>& getFirstName() const;
void setFirstName(const std::string& firstName); void setFirstName(optional<std::string> firstName);
const std::string& getLastName() const; const optional<std::string>& getLastName() const;
void setLastName(const std::string& lastName); void setLastName(optional<std::string> lastName);
bool isAllAdmins() const; bool isAllAdmins() const;
void setAllAdmins(bool allAdmins); void setAllAdmins(bool allAdmins);
void swap(Chat& other) noexcept;
const Chat& operator=(Chat other) noexcept;
private: private:
std::int64_t id_; std::int64_t id_;
Type type_; Type type_;
std::string title_; optional<std::string> title_;
std::string username_; optional<std::string> username_;
std::string firstName_; optional<std::string> firstName_;
std::string lastName_; optional<std::string> lastName_;
bool allAdmins_; bool allAdmins_;
}; };
using ChatPtr = std::shared_ptr<Chat>;
void swap(Chat& lhs, Chat& rhs);
Chat::Type chatTypeFromString(const std::string& str); Chat::Type chatTypeFromString(const std::string& str);
} }

View file

@ -17,8 +17,8 @@ public:
class ApiError : public std::runtime_error class ApiError : public std::runtime_error
{ {
public: public:
ApiError(int code, const std::string& message) ApiError(int code, std::string message)
: std::runtime_error(message), code_(code) : std::runtime_error(std::move(message)), code_(code)
{ {
} }

View file

@ -4,10 +4,12 @@
#include "User.hpp" #include "User.hpp"
#include "Chat.hpp" #include "Chat.hpp"
#include "Attachment.hpp" #include "Attachment.hpp"
#include "Optional.hpp"
#include <vector> #include <vector>
#include <ctime> #include <ctime>
#include <memory> #include <memory>
#include <boost/variant/variant.hpp>
namespace telebotxx { namespace telebotxx {
@ -30,9 +32,6 @@ public:
}; };
MessageEntity(); MessageEntity();
MessageEntity(const MessageEntity&);
MessageEntity(MessageEntity&&);
~MessageEntity();
Type getType() const; Type getType() const;
void setType(Type type); void setType(Type type);
@ -43,22 +42,18 @@ public:
size_t getLength() const; size_t getLength() const;
void setLength(size_t length); void setLength(size_t length);
const std::string& getUrl() const; const optional<std::string>& getUrl() const;
void setUrl(const std::string& url); void setUrl(std::string url);
const User& getUser() const; const optional<User>& getUser() const;
void setUser(const User& user); void setUser(User user);
void swap(MessageEntity& other) noexcept;
const MessageEntity& operator=(MessageEntity other);
private: private:
Type type_; Type type_;
int offset_; int offset_;
std::size_t length_; std::size_t length_;
std::string url_; optional<std::string> url_;
User user_; optional<User> user_;
}; };
MessageEntity::Type messageEntityTypeFromString(const std::string& str); MessageEntity::Type messageEntityTypeFromString(const std::string& str);
@ -72,60 +67,57 @@ class Message
{ {
public: public:
Message(); Message();
Message(const Message&);
Message(Message&&);
~Message();
int getId() const; int getId() const;
void setId(int id); void setId(int id);
const UserPtr getFrom() const; const optional<User>& getFrom() const;
void setFrom(UserPtr from); void setFrom(optional<User> from);
time_t getDate() const; time_t getDate() const;
void setDate(time_t date); void setDate(time_t date);
const Chat& getChat() const; const Chat& getChat() const;
void setChat(const Chat& chat); void setChat(Chat chat);
const UserPtr getForwardFrom() const; const optional<User>& getForwardFrom() const;
void setForwardFrom(UserPtr forwardFrom); void setForwardFrom(optional<User> forwardFrom);
const ChatPtr getForwardFromChat() const; const optional<Chat>& getForwardFromChat() const;
void setForwardFromChat(ChatPtr forwardFromChat); void setForwardFromChat(optional<Chat> forwardFromChat);
time_t getForwardDate() const; const optional<time_t>& getForwardDate() const;
void setForwardDate(time_t forwardDate); void setForwardDate(optional<time_t> forwardDate);
const MessagePtr getReplyToMessage() const; MessagePtr getReplyToMessage() const;
void setReplyToMessage(MessagePtr replyToMessage); void setReplyToMessage(MessagePtr replyToMessage);
time_t getEditDate() const; const optional<time_t>& getEditDate() const;
void setEditDate(time_t editDate); void setEditDate(optional<time_t> editDate);
const std::string& getText() const; const optional<std::string>& getText() const;
void setText(const std::string& text); void setText(optional<std::string> text);
const MessageEntities& getEntities() const; const optional<MessageEntities>& getEntities() const;
void setEntities(MessageEntities&& entities); void setEntities(optional<MessageEntities> entities);
const AttachmentPtr getAttachment() const; const optional<Attachment>& getAttachment() const;
void setAttachment(AttachmentPtr attachment); void setAttachment(optional<Attachment> attachment);
const std::string& getCaption() const; const optional<std::string>& getCaption() const;
void setCaption(const std::string& caption); void setCaption(optional<std::string> caption);
const UserPtr getNewChatMember() const; const optional<User>& getNewChatMember() const;
void setNewChatMember(UserPtr newChatMember); void setNewChatMember(optional<User> newChatMember);
const UserPtr getLeftChatMember() const; const optional<User>& getLeftChatMember() const;
void setLeftChatMember(UserPtr leftChatMember); void setLeftChatMember(optional<User> leftChatMember);
const std::string& getNewChatTitle() const; const optional<std::string>& getNewChatTitle() const;
void setNewChatTitle(const std::string& newChatTitle); void setNewChatTitle(optional<std::string> newChatTitle);
const PhotoSizeArrayPtr getNewChatPhoto() const; const optional<PhotoSizeArray> getNewChatPhoto() const;
void setNewChatPhoto(PhotoSizeArrayPtr newChatPhoto); void setNewChatPhoto(optional<PhotoSizeArray> newChatPhoto);
bool isDeleteChatPhoto() const; bool isDeleteChatPhoto() const;
void setDeleteChatPhoto(bool deleteChatPhoto); void setDeleteChatPhoto(bool deleteChatPhoto);
@ -139,48 +131,43 @@ public:
bool isChannelChatCreated() const; bool isChannelChatCreated() const;
void setChannelChatCreated(bool channelChatCreated); void setChannelChatCreated(bool channelChatCreated);
std::int64_t getMigrateToChatId() const; const optional<std::int64_t>& getMigrateToChatId() const;
void setMigrateToChatId(std::int64_t migrateToChatId); void setMigrateToChatId(optional<std::int64_t> migrateToChatId);
std::int64_t getMigrateFromChatId() const; const optional<std::int64_t>& getMigrateFromChatId() const;
void setMigrateFromChatId(std::int64_t migrateFromChatId); void setMigrateFromChatId(optional<std::int64_t> migrateFromChatId);
const MessagePtr getPinnedMessage() const; MessagePtr getPinnedMessage() const;
void setPinnedMessage(MessagePtr pinnedMessage); void setPinnedMessage(MessagePtr pinnedMessage);
void swap(Message& other) noexcept;
const Message& operator=(Message other) noexcept;
private: private:
int id_; int id_;
UserPtr from_; optional<User> from_;
std::time_t date_; std::time_t date_;
Chat chat_; Chat chat_;
UserPtr forwardFrom_; optional<User> forwardFrom_;
ChatPtr forwardFromChat_; optional<Chat> forwardFromChat_;
std::time_t forwardDate_; optional<int> forwardFromMessageId_;
optional<std::time_t> forwardDate_;
MessagePtr replyToMessage_; MessagePtr replyToMessage_;
std::time_t editDate_; optional<std::time_t> editDate_;
std::string text_; optional<std::string> text_;
MessageEntities entities_; optional<MessageEntities> entities_;
AttachmentPtr attachment_; optional<Attachment> attachment_;
std::string caption_; optional<std::string> caption_;
UserPtr newChatMember_; optional<User> newChatMember_;
UserPtr leftChatMember_; optional<User> leftChatMember_;
std::string newChatTitle_; optional<std::string> newChatTitle_;
PhotoSizeArrayPtr newChatPhoto_; optional<PhotoSizeArray> newChatPhoto_;
bool deleteChatPhoto_; bool deleteChatPhoto_;
bool groupChatCreated_; bool groupChatCreated_;
bool superGroupChatCreated_; bool superGroupChatCreated_;
bool channelChatCreated_; bool channelChatCreated_;
std::int64_t migrateToChatId_; optional<std::int64_t> migrateToChatId_;
std::int64_t migrateFromChatId_; optional<std::int64_t> migrateFromChatId_;
MessagePtr pinnedMessage_; MessagePtr pinnedMessage_;
}; };
void swap(Message& lhs, Message& rhs);
} }
#endif // TELEBOTXX_MESSAGE_HPP #endif // TELEBOTXX_MESSAGE_HPP

View file

@ -0,0 +1,15 @@
#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

@ -31,9 +31,6 @@ class ChatId
public: public:
ChatId(int); ChatId(int);
ChatId(const std::string&); ChatId(const std::string&);
ChatId(const ChatId&);
ChatId(ChatId&&);
~ChatId();
enum class Type { Id, Username }; enum class Type { Id, Username };
Type getType() const; Type getType() const;
@ -92,9 +89,6 @@ public:
explicit Photo(const Buffer&); explicit Photo(const Buffer&);
explicit Photo(const File&); explicit Photo(const File&);
explicit Photo(const Url&); explicit Photo(const Url&);
Photo(const Photo&);
Photo(Photo&&);
~Photo();
enum class Type { Id, Buffer, File, Url }; enum class Type { Id, Buffer, File, Url };
Type getType() const; Type getType() const;

View file

@ -15,59 +15,26 @@ public:
{ {
Message, Message,
EditedMessage, EditedMessage,
ChannelPost,
EditedChannelPost,
InlineQuery, InlineQuery,
ChosenInlineResult, ChosenInlineResult,
CallbackQuery CallbackQuery
}; };
Update(int id, Type type); Update(int id, Type type, std::unique_ptr<Message>);
Update(const Update&);
Update(Update&&);
virtual ~Update() = 0;
int getId() const; int getId() const;
Type getType() const; Type getType() const;
MessagePtr getMessage() const;
void swap(Update& other) noexcept;
private: private:
int id_; int id_;
Type updateType_; Type type_;
boost::variant<MessagePtr> value_;
}; };
using UpdatePtr = std::shared_ptr<Update>; using Updates = std::vector<Update>;
using Updates = std::vector<UpdatePtr>;
class MessageUpdate : public Update
{
public:
MessageUpdate(int id, const Message& message);
MessageUpdate(const MessageUpdate&);
MessageUpdate(MessageUpdate&&);
~MessageUpdate();
const Message& getMessage() const;
void swap(MessageUpdate& other) noexcept;
const MessageUpdate& operator=(MessageUpdate other);
private:
Message message_;
};
class EditedMessageUpdate : public MessageUpdate
{
public:
EditedMessageUpdate(int id, const Message& message);
EditedMessageUpdate(const EditedMessageUpdate&);
EditedMessageUpdate(EditedMessageUpdate&&);
~EditedMessageUpdate();
void swap(EditedMessageUpdate& other) noexcept;
const EditedMessageUpdate& operator=(EditedMessageUpdate other);
};
} }

View file

@ -1,6 +1,7 @@
#ifndef TELEBOTXX_USER_H #ifndef TELEBOTXX_USER_H
#define TELEBOTXX_USER_H #define TELEBOTXX_USER_H
#include "Optional.hpp"
#include <string> #include <string>
#include <memory> #include <memory>
@ -10,9 +11,6 @@ class User
{ {
public: public:
User(); User();
User(const User&);
User(User&&);
~User();
/// \brief Get id /// \brief Get id
int getId() const; int getId() const;
@ -24,36 +22,30 @@ public:
const std::string& getFirstName() const; const std::string& getFirstName() const;
/// \brief Set first name /// \brief Set first name
void setFirstName(const std::string& firstName); void setFirstName(std::string firstName);
/// \brief Get last name /// \brief Get last name
const std::string& getLastName() const; const optional<std::string>& getLastName() const;
/// \brief Set last name /// \brief Set last name
void setLastName(const std::string& lastName); void setLastName(optional<std::string> lastName);
/// \brief Get username /// \brief Get username
const std::string& getUsername() const; const optional<std::string>& getUsername() const;
/// \brief Set username /// \brief Set username
void setUsername(const std::string& username); void setUsername(optional<std::string> username);
/// \brief Get string representation of user /// \brief Get string representation of user
const std::string toString() const; const std::string toString() const;
void swap(User&) noexcept;
const User& operator=(User other);
private: private:
int id_; int id_;
std::string firstName_; std::string firstName_;
std::string lastName_; optional<std::string> lastName_;
std::string username_; optional<std::string> username_;
}; };
using UserPtr = std::shared_ptr<User>;
std::ostream& operator<<(std::ostream& os, const User& user); std::ostream& operator<<(std::ostream& os, const User& user);
} }

View file

@ -1,30 +1,9 @@
#include <telebotxx/Attachment.hpp> #include <telebotxx/Attachment.hpp>
#include <boost/variant.hpp>
namespace telebotxx { namespace telebotxx {
Attachment::Attachment(Type type)
: attachmentType_(type)
{
}
Attachment::Attachment(const Attachment&) = default;
Attachment::Attachment(Attachment&&) = default;
Attachment::~Attachment() = default;
Attachment::Type Attachment::getType() const
{
return attachmentType_;
}
void Attachment::swap(Attachment& other) noexcept
{
std::swap(attachmentType_, other.attachmentType_);
}
////////////////////////////////////////////////////////////////
PhotoSize::PhotoSize() PhotoSize::PhotoSize()
: width_(-1), : width_(-1),
height_(-1), height_(-1),
@ -32,12 +11,6 @@ PhotoSize::PhotoSize()
{ {
} }
PhotoSize::PhotoSize(const PhotoSize&) = default;
PhotoSize::PhotoSize(PhotoSize&&) = default;
PhotoSize::~PhotoSize() = default;
const std::string& PhotoSize::getFileId() const const std::string& PhotoSize::getFileId() const
{ {
return fileId_; return fileId_;
@ -68,81 +41,24 @@ void PhotoSize::setHeight(int height)
height_ = height; height_ = height;
} }
int PhotoSize::getFileSize() const const optional<int>& PhotoSize::getFileSize() const
{ {
return fileSize_; return fileSize_;
} }
void PhotoSize::setFileSize(int fileSize) void PhotoSize::setFileSize(optional<int> fileSize)
{ {
fileSize_ = fileSize; fileSize_ = fileSize;
} }
void PhotoSize::swap(PhotoSize& other) noexcept
{
using std::swap;
swap(fileId_, other.fileId_);
swap(width_, other.width_);
swap(height_, other.height_);
swap(fileSize_, other.fileSize_);
}
const PhotoSize& PhotoSize::operator=(PhotoSize other) noexcept
{
swap(other);
return *this;
}
////////////////////////////////////////////////////////////////
PhotoSizeArray::PhotoSizeArray()
: Attachment(Attachment::Type::PhotoSizeArray)
{
}
PhotoSizeArray::PhotoSizeArray(const PhotoSizeArray&) = default;
PhotoSizeArray::PhotoSizeArray(PhotoSizeArray&&) = default;
PhotoSizeArray::~PhotoSizeArray() = default;
const std::vector<PhotoSize>& PhotoSizeArray::getArray() const
{
return array_;
}
void PhotoSizeArray::setArray(const std::vector<PhotoSize>& array)
{
array_ = array;
}
void PhotoSizeArray::swap(PhotoSizeArray& other) noexcept
{
using std::swap;
swap(array_, other.array_);
}
const PhotoSizeArray& PhotoSizeArray::operator=(PhotoSizeArray other) noexcept
{
swap(other);
return *this;
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Audio::Audio() Audio::Audio()
: Attachment(Type::Audio), : duration_(-1),
duration_(-1),
fileSize_(-1) fileSize_(-1)
{ {
} }
Audio::Audio(const Audio&) = default;
Audio::Audio(Audio&&) = default;
Audio::~Audio() = default;
const std::string& Audio::getFileId() const const std::string& Audio::getFileId() const
{ {
return fileId_; return fileId_;
@ -163,159 +79,110 @@ void Audio::setDuration(int duration)
duration_ = duration; duration_ = duration;
} }
const std::string& Audio::getPerformer() const const optional<std::string>& Audio::getPerformer() const
{ {
return performer_; return performer_;
} }
void Audio::setPerformer(const std::string& performer) void Audio::setPerformer(optional<std::string> performer)
{ {
performer_ = performer; performer_ = std::move(performer);
} }
const std::string& Audio::getTitle() const const optional<std::string>& Audio::getTitle() const
{ {
return title_; return title_;
} }
void Audio::setTitle(const std::string& title) void Audio::setTitle(optional<std::string> title)
{ {
title_ = title; title_ = title;
} }
const std::string& Audio::getMimeType() const const optional<std::string>& Audio::getMimeType() const
{ {
return mimeType_; return mimeType_;
} }
void Audio::setMimeType(const std::string& mimeType) void Audio::setMimeType(optional<std::string> mimeType)
{ {
mimeType_ = mimeType; mimeType_ = mimeType;
} }
int Audio::getFileSize() const const optional<int>& Audio::getFileSize() const
{ {
return fileSize_; return fileSize_;
} }
void Audio::setFileSize(int fileSize) void Audio::setFileSize(optional<int> fileSize)
{ {
fileSize_ = fileSize; fileSize_ = fileSize;
} }
void Audio::swap(Audio& other) noexcept
{
Attachment::swap(other);
using std::swap;
swap(fileId_, other.fileId_);
swap(duration_, other.duration_);
swap(performer_, other.performer_);
swap(title_, other.title_);
swap(mimeType_, other.mimeType_);
swap(fileSize_, other.fileSize_);
}
const Audio& Audio::operator=(Audio other) noexcept
{
swap(other);
return *this;
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Document::Document() Document::Document()
: Attachment(Type::Document), : fileSize_(-1)
fileSize_(-1)
{ {
} }
Document::Document(const Document&) = default;
Document::Document(Document&&) = default;
Document::~Document() = default;
const std::string& Document::getFileId() const const std::string& Document::getFileId() const
{ {
return fileId_; return fileId_;
} }
void Document::setFileId(const std::string& fileId) void Document::setFileId(std::string fileId)
{ {
fileId_ = fileId; fileId_ = fileId;
} }
const PhotoSizePtr Document::getThumb() const const optional<PhotoSize>& Document::getThumb() const
{ {
return thumb_; return thumb_;
} }
void Document::setThumb(const PhotoSizePtr& thumb) void Document::setThumb(optional<PhotoSize> thumb)
{ {
thumb_ = thumb; thumb_ = thumb;
} }
const std::string& Document::getFileName() const const optional<std::string>& Document::getFileName() const
{ {
return fileName_; return fileName_;
} }
void Document::setFileName(const std::string& fileName) void Document::setFileName(optional<std::string> fileName)
{ {
fileName_ = fileName; fileName_ = fileName;
} }
const std::string& Document::getMimeType() const const optional<std::string>& Document::getMimeType() const
{ {
return mimeType_; return mimeType_;
} }
void Document::setMimeType(const std::string& mimeType) void Document::setMimeType(optional<std::string> mimeType)
{ {
mimeType_ = mimeType; mimeType_ = mimeType;
} }
int Document::getFileSize() const const optional<int>& Document::getFileSize() const
{ {
return fileSize_; return fileSize_;
} }
void Document::setFileSize(int fileSize) void Document::setFileSize(optional<int> fileSize)
{ {
fileSize_ = fileSize; fileSize_ = fileSize;
} }
void Document::swap(Document& other) noexcept
{
Attachment::swap(other);
using std::swap;
swap(fileId_, other.fileId_);
swap(thumb_, other.thumb_);
swap(fileName_, other.fileName_);
swap(mimeType_, other.mimeType_);
swap(fileSize_, other.fileSize_);
}
const Document& Document::operator=(Document other) noexcept
{
swap(other);
return *this;
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Sticker::Sticker() Sticker::Sticker()
: Attachment(Type::Sticker), : fileSize_(-1)
fileSize_(-1)
{ {
} }
Sticker::Sticker(const Sticker&) = default;
Sticker::Sticker(Sticker&&) = default;
Sticker::~Sticker() = default;
const std::string& Sticker::getFileId() const const std::string& Sticker::getFileId() const
{ {
return fileId_; return fileId_;
@ -346,79 +213,81 @@ void Sticker::setHeight(int height)
height_ = height; height_ = height;
} }
const PhotoSizePtr Sticker::getThumb() const const optional<PhotoSize>& Sticker::getThumb() const
{ {
return thumb_; return thumb_;
} }
void Sticker::setThumb(const PhotoSizePtr& thumb) void Sticker::setThumb(optional<PhotoSize> thumb)
{ {
thumb_ = thumb; thumb_ = thumb;
} }
const std::string& Sticker::getEmoji() const const optional<std::string>& Sticker::getEmoji() const
{ {
return emoji_; return emoji_;
} }
void Sticker::setEmoji(const std::string& emoji) void Sticker::setEmoji(optional<std::string> emoji)
{ {
emoji_ = emoji; emoji_ = emoji;
} }
int Sticker::getFileSize() const const optional<int>& Sticker::getFileSize() const
{ {
return fileSize_; return fileSize_;
} }
void Sticker::setFileSize(int fileSize) void Sticker::setFileSize(optional<int> fileSize)
{ {
fileSize_ = fileSize; fileSize_ = fileSize;
} }
void Sticker::swap(Sticker& other) noexcept
{
Attachment::swap(other);
using std::swap;
swap(fileId_, other.fileId_);
swap(width_, other.width_);
swap(height_, other.height_);
swap(thumb_, other.thumb_);
swap(emoji_, other.emoji_);
swap(fileSize_, other.fileSize_);
}
const Sticker& Sticker::operator=(Sticker other) noexcept
{
swap(other);
return *this;
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
void swap(PhotoSize& lhs, PhotoSize& rhs) Attachment::Attachment(PhotoSizeArray photos)
: type_(Type::PhotoSizeArray), value_(std::move(photos))
{ {
lhs.swap(rhs);
} }
void swap(PhotoSizeArray& lhs, PhotoSizeArray& rhs) Attachment::Attachment(Audio audio)
: type_(Type::Audio), value_(std::move(audio))
{ {
lhs.swap(rhs);
} }
void swap(Audio& lhs, Audio& rhs) Attachment::Attachment(Document document)
: type_(Type::Document), value_(std::move(document))
{ {
lhs.swap(rhs);
} }
void swap(Document& lhs, Document& rhs) Attachment::Attachment(Sticker sticker)
: type_(Type::Sticker), value_(std::move(sticker))
{ {
lhs.swap(rhs);
} }
void swap(Sticker& lhs, Sticker& rhs) Attachment::Type Attachment::getType() const
{ {
lhs.swap(rhs); return type_;
}
const PhotoSizeArray& Attachment::getPhotoSizeArray() const
{
return boost::get<PhotoSizeArray>(value_);
}
const Audio& Attachment::getAudio() const
{
return boost::get<Audio>(value_);;
}
const Document& Attachment::getDocument() const
{
return boost::get<Document>(value_);
}
const Sticker& Attachment::getSticker() const
{
return boost::get<Sticker>(value_);;
} }
} }

View file

@ -34,7 +34,7 @@ public:
doc.Parse(response.c_str()); doc.Parse(response.c_str());
checkResponse(doc); checkResponse(doc);
return *parseUser(doc, "result", REQUIRED); 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)
@ -133,7 +133,7 @@ public:
doc.Parse(response.c_str()); doc.Parse(response.c_str());
checkResponse(doc); checkResponse(doc);
return *parseUpdates(doc, "result", REQUIRED); return parseUpdates(doc, "result");
} }
std::string getTelegramMainUrl() const std::string getTelegramMainUrl() const

View file

@ -5,7 +5,7 @@ message(STATUS "Configuring telebotxx")
include(${CMAKE_SOURCE_DIR}/cmake/RequireCXX14.cmake) include(${CMAKE_SOURCE_DIR}/cmake/RequireCXX14.cmake)
RequireCXX14() RequireCXX14()
find_package(Boost REQUIRED) find_package(Boost 1.56 REQUIRED)
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
# Add required compiler flags # Add required compiler flags

View file

@ -10,12 +10,6 @@ Chat::Chat()
{ {
} }
Chat::Chat(const Chat&) = default;
Chat::Chat(Chat&&) = default;
Chat::~Chat() = default;
std::int64_t Chat::getId() const std::int64_t Chat::getId() const
{ {
return id_; return id_;
@ -36,42 +30,42 @@ void Chat::setType(Chat::Type type)
type_ = type; type_ = type;
} }
const std::string& Chat::getTitle() const const optional<std::string>& Chat::getTitle() const
{ {
return title_; return title_;
} }
void Chat::setTitle(const std::string& title) void Chat::setTitle(optional<std::string> title)
{ {
title_ = title; title_ = title;
} }
const std::string& Chat::getUsername() const const optional<std::string>& Chat::getUsername() const
{ {
return username_; return username_;
} }
void Chat::setUsername(const std::string& username) void Chat::setUsername(optional<std::string> username)
{ {
username_ = username; username_ = username;
} }
const std::string& Chat::getFirstName() const const optional<std::string>& Chat::getFirstName() const
{ {
return firstName_; return firstName_;
} }
void Chat::setFirstName(const std::string& firstName) void Chat::setFirstName(optional<std::string> firstName)
{ {
firstName_ = firstName; firstName_ = firstName;
} }
const std::string& Chat::getLastName() const const optional<std::string>& Chat::getLastName() const
{ {
return lastName_; return lastName_;
} }
void Chat::setLastName(const std::string& lastName) void Chat::setLastName(optional<std::string> lastName)
{ {
lastName_ = lastName; lastName_ = lastName;
} }
@ -86,29 +80,6 @@ void Chat::setAllAdmins(bool allAdmins)
allAdmins_ = allAdmins; allAdmins_ = allAdmins;
} }
void Chat::swap(Chat& other) noexcept
{
using std::swap;
swap(id_, other.id_);
swap(type_, other.type_);
swap(title_, other.title_);
swap(username_, other.username_);
swap(firstName_, other.firstName_);
swap(lastName_, other.lastName_);
swap(allAdmins_, other.allAdmins_);
}
const Chat& Chat::operator=(Chat other) noexcept
{
swap(other);
return *this;
}
void swap(Chat& lhs, Chat& rhs)
{
lhs.swap(rhs);
}
Chat::Type chatTypeFromString(const std::string& str) Chat::Type chatTypeFromString(const std::string& str)
{ {
if (str == "private") if (str == "private")

View file

@ -1,45 +1,27 @@
#include "JsonObjects.hpp" #include "JsonObjects.hpp"
#include <telebotxx/Exception.hpp>
#include <cstdint> #include <cstdint>
namespace telebotxx { namespace telebotxx {
namespace impl { namespace impl {
template<typename T> bool is(const rapidjson::Value& obj);
template<> bool is<int>(const rapidjson::Value& obj) { return obj.IsInt(); } 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<std::int64_t>(const rapidjson::Value& obj) { return obj.IsInt64(); }
template<> bool is<bool>(const rapidjson::Value& obj) { return obj.IsBool(); } template<> bool is<bool>(const rapidjson::Value& obj) { return obj.IsBool(); }
template<> bool is<std::string>(const rapidjson::Value& obj) { return obj.IsString(); } template<> bool is<std::string>(const rapidjson::Value& obj) { return obj.IsString(); }
template<typename T> const T get(const rapidjson::Value& obj);
template<> const int get(const rapidjson::Value& obj) { return obj.GetInt(); } 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 std::int64_t get(const rapidjson::Value& obj) { return obj.GetInt64(); }
template<> const bool get(const rapidjson::Value& obj) { return obj.GetBool(); } template<> const bool get(const rapidjson::Value& obj) { return obj.GetBool(); }
template<> const std::string get(const rapidjson::Value& obj) { return obj.GetString(); } template<> const std::string get(const rapidjson::Value& obj) { return obj.GetString(); }
template<typename T> const T null();
template<> const int null() { return 0; }
template<> const std::int64_t null() { return 0; }
template<> const bool null() { return false; }
template<> const std::string null() { return ""; }
} }
template<typename T> bool check(const rapidjson::Value& obj, const char* name)
const T parse(const rapidjson::Value& obj, const char* name, bool required)
{ {
if (obj.HasMember(name)) if (auto value = parse<bool>(obj, name, OPTIONAL))
{ return *value;
if (impl::is<T>(obj[name]))
return impl::get<T>(obj[name]);
else else
throw ParseError(std::string("Field '") + name + "' has invalid type"); return false;
}
else if (required)
throw ParseError(std::string("Field '") + name + "' not found");
else
return impl::null<T>();
} }
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)
@ -84,218 +66,218 @@ const rapidjson::Value& parseArray(const rapidjson::Value& parent, const char* n
} }
} }
std::unique_ptr<PhotoSize> parsePhotoSize(const rapidjson::Value& obj) template <>
{ optional<Chat> parse<Chat>(const rapidjson::Value& parent, const char* name, bool required)
auto photo = std::make_unique<PhotoSize>();
photo->setFileId(parse<std::string>(obj, "file_id", REQUIRED));
photo->setWidth(parse<int>(obj, "width", REQUIRED));
photo->setHeight(parse<int>(obj, "height", REQUIRED));
photo->setFileSize(parse<int>(obj, "file_size", OPTIONAL));
return photo;
}
std::unique_ptr<PhotoSize> parsePhotoSize(const rapidjson::Value& parent, const char* name, bool required)
{ {
optional<Chat> chat;
bool found; bool found;
auto& obj = parseObject(parent, name, required, found); auto& obj = parseObject(parent, name, required, found);
if (found) if (found)
{ {
return parsePhotoSize(obj); chat.emplace();
chat->setId(require<std::int64_t>(obj, "id"));
chat->setType(chatTypeFromString(require<std::string>(obj, "type")));
chat->setTitle(allow<std::string>(obj, "title"));
chat->setUsername(parse<std::string>(obj, "username", OPTIONAL));
chat->setFirstName(parse<std::string>(obj, "first_name", OPTIONAL));
chat->setLastName(parse<std::string>(obj, "last_name", OPTIONAL));
chat->setAllAdmins(check(obj, "all_members_are_administrators"));
} }
else return chat;
return nullptr;
} }
std::unique_ptr<PhotoSizeArray> parsePhotoSizeArray(const rapidjson::Value& parent, const char* name, bool required) template <>
optional<User> parse<User>(const rapidjson::Value& parent, const char* name, bool required)
{ {
optional<User> user;
bool found;
auto& obj = parseObject(parent, name, required, found);
if (found)
{
user.emplace();
user->setId(require<int>(obj, "id"));
user->setFirstName(require<std::string>(obj, "first_name"));
user->setLastName(allow<std::string>(obj, "last_name"));
}
return user;
}
PhotoSize parsePhotoSize(const rapidjson::Value& obj)
{
PhotoSize photo;
photo.setFileId(require<std::string>(obj, "file_id"));
photo.setWidth(require<int>(obj, "width"));
photo.setHeight(require<int>(obj, "height"));
photo.setFileSize(allow<int>(obj, "file_size"));
return photo;
}
template <>
optional<PhotoSize> parse<PhotoSize>(const rapidjson::Value& parent, const char* name, bool required)
{
optional<PhotoSize> photo;
bool found;
auto& obj = parseObject(parent, name, required, found);
if (found)
{
photo.emplace(parsePhotoSize(obj));
}
return photo;
}
template <>
optional<PhotoSizeArray> parse<PhotoSizeArray>(const rapidjson::Value& parent, const char* name, bool required)
{
optional<PhotoSizeArray> photos;
bool found; bool found;
auto& obj = parseArray(parent, name, required, found); auto& obj = parseArray(parent, name, required, found);
if (found) if (found)
{ {
std::vector<PhotoSize> photos; photos.emplace();
photos->reserve(obj.GetArray().Size());
for (auto& elem : obj.GetArray()) for (auto& elem : obj.GetArray())
{ photos->emplace_back(parsePhotoSize(elem));
auto photo = parsePhotoSize(elem);
photos.push_back(std::move(*photo));
} }
auto result = std::make_unique<PhotoSizeArray>(); return photos;
result->setArray(photos);
return result;
}
else
return nullptr;
} }
std::unique_ptr<Audio> parseAudio(const rapidjson::Value& parent, const char* name, bool required) template <>
optional<Audio> parse<Audio>(const rapidjson::Value& parent, const char* name, bool required)
{ {
optional<Audio> audio;
bool found; bool found;
auto& obj = parseObject(parent, name, required, found); auto& obj = parseObject(parent, name, required, found);
if (found) if (found)
{ {
auto audio = std::make_unique<Audio>(); audio->setFileId(require<std::string>(obj, "file_id"));
audio->setFileId(parse<std::string>(obj, "file_id", REQUIRED)); audio->setDuration(require<int>(obj, "duration"));
audio->setDuration(parse<int>(obj, "duration", REQUIRED)); audio->setPerformer(allow<std::string>(obj, "performer"));
audio->setPerformer(parse<std::string>(obj, "performer", OPTIONAL)); audio->setTitle(allow<std::string>(obj, "title"));
audio->setTitle(parse<std::string>(obj, "title", OPTIONAL)); audio->setMimeType(allow<std::string>(obj, "mime_type"));
audio->setMimeType(parse<std::string>(obj, "mime_type", OPTIONAL)); audio->setFileSize(allow<int>(obj, "file_size"));
audio->setFileSize(parse<int>(obj, "file_size", OPTIONAL)); }
return audio; return audio;
}
else
return nullptr;
} }
std::unique_ptr<Document> parseDocument(const rapidjson::Value& parent, const char* name, bool required) template <>
optional<Document> parse<Document>(const rapidjson::Value& parent, const char* name, bool required)
{ {
optional<Document> document;
bool found; bool found;
auto& obj = parseObject(parent, name, required, found); auto& obj = parseObject(parent, name, required, found);
if (found) if (found)
{ {
auto document = std::make_unique<Document>(); document.emplace();
document->setFileId(parse<std::string>(obj, "file_id", REQUIRED)); document->setFileId(require<std::string>(obj, "file_id"));
document->setThumb(parsePhotoSize(obj, "thumb", OPTIONAL)); document->setThumb(allow<PhotoSize>(obj, "thumb"));
document->setFileName(parse<std::string>(obj, "file_name", OPTIONAL)); document->setFileName(allow<std::string>(obj, "file_name"));
document->setMimeType(parse<std::string>(obj, "mime_type", OPTIONAL)); document->setMimeType(allow<std::string>(obj, "mime_type"));
document->setFileSize(parse<int>(obj, "file_size", OPTIONAL)); document->setFileSize(allow<int>(obj, "file_size"));
}
return document; return document;
}
else
return nullptr;
} }
std::unique_ptr<Sticker> parseSticker(const rapidjson::Value& parent, const char* name, bool required) template <>
optional<Sticker> parse<Sticker>(const rapidjson::Value& parent, const char* name, bool required)
{ {
optional<Sticker> sticker;
bool found; bool found;
auto& obj = parseObject(parent, name, required, found); auto& obj = parseObject(parent, name, required, found);
if (found) if (found)
{ {
auto sticker = std::make_unique<Sticker>(); sticker.emplace();
sticker->setFileId(parse<std::string>(obj, "file_id", REQUIRED)); sticker->setFileId(require<std::string>(obj, "file_id"));
sticker->setWidth(parse<int>(obj, "width", REQUIRED)); sticker->setWidth(require<int>(obj, "width"));
sticker->setHeight(parse<int>(obj, "height", REQUIRED)); sticker->setHeight(require<int>(obj, "height"));
sticker->setThumb(parsePhotoSize(obj, "thumb", OPTIONAL)); sticker->setThumb(allow<PhotoSize>(obj, "thumb"));
sticker->setEmoji(parse<std::string>(obj, "emoji", OPTIONAL)); sticker->setEmoji(allow<std::string>(obj, "emoji"));
sticker->setFileSize(parse<int>(obj, "file_size", OPTIONAL)); sticker->setFileSize(allow<int>(obj, "file_size"));
return sticker;
} }
else return sticker;
return nullptr; }
template <>
optional<Attachment> parse<Attachment>(const rapidjson::Value& parent, const char* name, bool required)
{
optional<Attachment> attachment;
if (auto photo = allow<PhotoSizeArray>(parent, "photo"))
attachment.emplace(std::move(*photo));
else if (auto audio = allow<Audio>(parent, "audio"))
attachment.emplace(std::move(*audio));
else if (auto document = allow<Document>(parent, "document"))
attachment.emplace(std::move(*document));
else if (auto sticker = allow<Sticker>(parent, "sticker"))
attachment.emplace(std::move(*sticker));
/// \todo Other attachments
return attachment;
} }
std::unique_ptr<Message> parseMessage(const rapidjson::Value& parent, const char* name, bool required) std::unique_ptr<Message> parseMessage(const rapidjson::Value& parent, const char* name, bool required)
{ {
std::unique_ptr<Message> message;
bool found; bool found;
auto& obj = parseObject(parent, name, required, found); auto& obj = parseObject(parent, name, required, found);
if (found) if (found)
{ {
auto message = std::make_unique<Message>(); message = std::make_unique<Message>();
message->setId(require<int>(obj, "message_id"));
message->setId(parse<int>(obj, "message_id", REQUIRED)); message->setFrom(allow<User>(obj, "from"));
message->setFrom(parseUser(obj, "from", OPTIONAL)); message->setDate(require<int>(obj, "date"));
message->setDate(parse<int>(obj, "date", REQUIRED)); message->setChat(require<Chat>(obj, "chat"));
message->setChat(*parseChat(obj, "chat", REQUIRED)); message->setForwardFrom(allow<User>(obj, "forward_from"));
message->setForwardFrom(parseUser(obj, "forward_from", OPTIONAL)); message->setForwardFromChat(allow<Chat>(obj, "forward_from_chat"));
message->setForwardFromChat(parseChat(obj, "forward_from_chat", OPTIONAL)); message->setForwardDate(allow<std::int64_t>(obj, "forward_date"));
message->setForwardDate(parse<int>(obj, "forward_date", OPTIONAL));
message->setReplyToMessage(parseMessage(obj, "reply_to_message", OPTIONAL)); message->setReplyToMessage(parseMessage(obj, "reply_to_message", OPTIONAL));
message->setEditDate(parse<int>(obj, "edit_date", OPTIONAL)); message->setEditDate(allow<std::int64_t>(obj, "edit_date"));
message->setText(parse<std::string>(obj, "text", OPTIONAL)); message->setText(parse<std::string>(obj, "text", OPTIONAL));
//message->setEntities(parseEntities(obj, "entities", OPTIONAL)); //message->setEntities(parseEntities(obj, "entities", OPTIONAL));
message->setAttachment(allow<Attachment>(obj, ""));
/// \todo: Parse one of the possible attachments message->setCaption(allow<std::string>(obj, "caption"));
std::shared_ptr<Attachment> attachment; message->setNewChatMember(allow<User>(obj, "new_chat_member"));
if (!(attachment = parsePhotoSizeArray(obj, "photo", OPTIONAL))) message->setLeftChatMember(allow<User>(obj, "left_chat_member"));
if (!(attachment = parseAudio(obj, "audio", OPTIONAL))) message->setNewChatTitle(allow<std::string>(obj, "new_chat_title"));
if (!(attachment = parseDocument(obj, "document", OPTIONAL))) message->setNewChatPhoto(allow<PhotoSizeArray>(obj, "new_chat_photo"));
attachment = parseSticker(obj, "sticker", OPTIONAL); message->setDeleteChatPhoto(check(obj, "delete_chat_photo"));
message->setAttachment(attachment); message->setGroupChatCreated(check(obj, "group_chat_created"));
message->setSuperGroupChatCreated(check(obj, "supergroup_chat_created"));
message->setCaption(parse<std::string>(obj, "caption", OPTIONAL)); message->setChannelChatCreated(check(obj, "channel_chat_created"));
message->setNewChatMember(parseUser(obj, "new_chat_member", OPTIONAL)); message->setMigrateToChatId(allow<std::int64_t>(obj, "migrate_to_chat_id"));
message->setLeftChatMember(parseUser(obj, "left_chat_member", OPTIONAL)); message->setMigrateFromChatId(allow<std::int64_t>(obj, "migrate_from_chat_id"));
message->setNewChatTitle(parse<std::string>(obj, "new_chat_title", OPTIONAL));
message->setNewChatPhoto(parsePhotoSizeArray(obj, "new_chat_photo", OPTIONAL));
message->setDeleteChatPhoto(parse<bool>(obj, "delete_chat_photo", OPTIONAL));
message->setGroupChatCreated(parse<bool>(obj, "group_chat_created", OPTIONAL));
message->setSuperGroupChatCreated(parse<bool>(obj, "supergroup_chat_created", OPTIONAL));
message->setChannelChatCreated(parse<bool>(obj, "channel_chat_created", OPTIONAL));
message->setMigrateToChatId(parse<std::int64_t>(obj, "migrate_to_chat_id", OPTIONAL));
message->setMigrateFromChatId(parse<std::int64_t>(obj, "migrate_from_chat_id", OPTIONAL));
message->setPinnedMessage(parseMessage(obj, "pinned_message", OPTIONAL)); message->setPinnedMessage(parseMessage(obj, "pinned_message", OPTIONAL));
}
return message; return message;
}
else
return nullptr;
} }
std::unique_ptr<Chat> parseChat(const rapidjson::Value& parent, const char* name, bool required) /// \todo Other updates
Update parseUpdate(const rapidjson::Value& obj)
{ {
bool found; int id = require<int>(obj, "update_id");
auto& obj = parseObject(parent, name, required, found);
if (found)
{
auto chat = std::make_unique<Chat>();
chat->setId(parse<std::int64_t>(obj, "id", REQUIRED));
chat->setType(chatTypeFromString(parse<std::string>(obj, "type", REQUIRED)));
chat->setTitle(parse<std::string>(obj, "title", OPTIONAL));
chat->setUsername(parse<std::string>(obj, "username", OPTIONAL));
chat->setFirstName(parse<std::string>(obj, "first_name", OPTIONAL));
chat->setLastName(parse<std::string>(obj, "last_name", OPTIONAL));
chat->setAllAdmins(parse<bool>(obj, "all_members_are_administrators", OPTIONAL));
return chat;
}
else
return nullptr;
}
std::unique_ptr<Update> parseUpdate(const rapidjson::Value& obj)
{
int id = parse<int>(obj, "update_id", REQUIRED);
std::unique_ptr<Message> message; std::unique_ptr<Message> message;
if ((message = parseMessage(obj, "message", OPTIONAL))) if ((message = parseMessage(obj, "message", OPTIONAL)))
return std::make_unique<MessageUpdate>(id, *message); return Update(id, Update::Type::Message, std::move(message));
else if ((message = parseMessage(obj, "edited_message", OPTIONAL))) else if ((message = parseMessage(obj, "edited_message", OPTIONAL)))
return std::make_unique<EditedMessageUpdate>(id, *message); return Update(id, Update::Type::EditedMessage, std::move(message));
/// \todo: other updates else if ((message = parseMessage(obj, "channel_post", OPTIONAL)))
return Update(id, Update::Type::ChannelPost, std::move(message));
else if ((message = parseMessage(obj, "edited_channel_post", OPTIONAL)))
return Update(id, Update::Type::EditedChannelPost, std::move(message));
else else
throw ParseError("Unknown update type"); throw ParseError("Unknown update type");
} }
std::unique_ptr<Updates> parseUpdates(const rapidjson::Value& parent, const char* name, bool required) Updates parseUpdates(const rapidjson::Value& parent, const char* name)
{ {
Updates updates;
bool found; bool found;
auto& obj = parseArray(parent, name, required, found); auto& obj = parseArray(parent, name, REQUIRED, found);
if (found) if (found)
{ {
std::vector<UpdatePtr> updates; updates.reserve(obj.GetArray().Size());
for (auto& elem : obj.GetArray()) for (auto& elem : obj.GetArray())
{ updates.emplace_back(parseUpdate(elem));
auto update = parseUpdate(elem);
updates.emplace_back(std::move(update));
} }
return std::make_unique<Updates>(std::move(updates)); return updates;
}
else
return nullptr;
}
std::unique_ptr<User> parseUser(const rapidjson::Value& parent, const char* name, bool required)
{
bool found;
auto& obj = parseObject(parent, name, required, found);
if (found)
{
auto user = std::make_unique<User>();
user->setId(parse<int>(obj, "id", REQUIRED));
user->setFirstName(parse<std::string>(obj, "first_name", REQUIRED));
user->setLastName(parse<std::string>(obj, "last_name", OPTIONAL));
user->setUsername(parse<std::string>(obj, "username", OPTIONAL));
return user;
}
else
return nullptr;
} }
void checkResponse(const rapidjson::Document& doc) void checkResponse(const rapidjson::Document& doc)
@ -304,11 +286,11 @@ void checkResponse(const rapidjson::Document& doc)
throw ParseError("Object expected"); throw ParseError("Object expected");
// Get status // Get status
bool ok = parse<bool>(doc, "ok", REQUIRED); bool ok = require<bool>(doc, "ok");
if (!ok) if (!ok)
{ {
int code = parse<int>(doc, "error_code", REQUIRED); int code = require<int>(doc, "error_code");
std::string description(parse<std::string>(doc, "description", REQUIRED)); std::string description(require<std::string>(doc, "description"));
throw ApiError(code, description); throw ApiError(code, description);
} }
} }

View file

@ -5,6 +5,8 @@
#include <telebotxx/Message.hpp> #include <telebotxx/Message.hpp>
#include <telebotxx/Update.hpp> #include <telebotxx/Update.hpp>
#include <telebotxx/User.hpp> #include <telebotxx/User.hpp>
#include <telebotxx/Optional.hpp>
#include <telebotxx/Exception.hpp>
#include <memory> #include <memory>
@ -15,19 +17,58 @@ namespace telebotxx {
const bool REQUIRED = true; const bool REQUIRED = true;
const bool OPTIONAL = false; const bool OPTIONAL = false;
/// \brief Parse JSON object to Chat namespace impl {
/// \param parent reference to parent JSON object
/// \param name field with Chat object template<typename T> bool is(const rapidjson::Value& obj);
/// \param required REQUIRED or OPTIONAL template<> bool is<int>(const rapidjson::Value& obj);
/// \return pointer to Chat template<> bool is<std::int64_t>(const rapidjson::Value& obj);
std::unique_ptr<Chat> parseChat(const rapidjson::Value& parent, const char* name, bool required); 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>
optional<T> parse(const rapidjson::Value& obj, const char* name, bool required)
{
if (obj.HasMember(name))
{
if (impl::is<T>(obj[name]))
return impl::get<T>(obj[name]);
else
throw ParseError(std::string("Field '") + name + "' has invalid type");
}
else if (required)
throw ParseError(std::string("Field '") + name + "' not found");
else
return boost::none;
}
template <typename T>
T require(const rapidjson::Value& obj, const char* name)
{
return *parse<T>(obj, name, REQUIRED);
}
template <typename T>
optional<T> allow(const rapidjson::Value& obj, const char* name)
{
return parse<T>(obj, name, OPTIONAL);
}
bool check(const rapidjson::Value& obj, const char* name);
/// \brief Parse JSON object to User /// \brief Parse JSON object to User
/// \param parent reference to parent JSON object /// \param parent reference to parent JSON object
/// \param name field with Document object /// \param name field with Document object
/// \param required REQUIRED or OPTIONAL /// \param required REQUIRED or OPTIONAL
/// \return pointer to User /// \return pointer to User
std::unique_ptr<User> parseUser(const rapidjson::Value& parent, const char* name, bool required); template<> optional<User> parse<User>(const rapidjson::Value& parent, const char* name, bool required);
/// \brief Parse JSON object to Message /// \brief Parse JSON object to Message
/// \param parent reference to parent JSON object /// \param parent reference to parent JSON object
@ -39,9 +80,8 @@ std::unique_ptr<Message> parseMessage(const rapidjson::Value& parent, const char
/// \brief Parse JSON array of Update /// \brief Parse JSON array of Update
/// \param parent reference to parent JSON object /// \param parent reference to parent JSON object
/// \param name field with array of Update objects /// \param name field with array of Update objects
/// \param required REQUIRED or OPTIONAL
/// \return Updates (vector of UpdatePtr> /// \return Updates (vector of UpdatePtr>
std::unique_ptr<Updates> parseUpdates(const rapidjson::Value& parent, const char* name, bool required); Updates parseUpdates(const rapidjson::Value& parent, const char* name);
/// \brief Check JSON response /// \brief Check JSON response
/// ///

View file

@ -9,12 +9,6 @@ MessageEntity::MessageEntity()
{ {
} }
MessageEntity::MessageEntity(const MessageEntity&) = default;
MessageEntity::MessageEntity(MessageEntity&&) = default;
MessageEntity::~MessageEntity() = default;
MessageEntity::Type MessageEntity::getType() const MessageEntity::Type MessageEntity::getType() const
{ {
return type_; return type_;
@ -45,40 +39,24 @@ void MessageEntity::setLength(size_t length)
length_ = length; length_ = length;
} }
const std::string& MessageEntity::getUrl() const const optional<std::string>& MessageEntity::getUrl() const
{ {
return url_; return url_;
} }
void MessageEntity::setUrl(const std::string& url) void MessageEntity::setUrl(std::string url)
{ {
url_ = url; url_ = std::move(url);
} }
const User& MessageEntity::getUser() const const optional<User>& MessageEntity::getUser() const
{ {
return user_; return user_;
} }
void MessageEntity::setUser(const User& user) void MessageEntity::setUser(User user)
{ {
user_ = user; user_ = std::move(user);
}
void MessageEntity::swap(MessageEntity& other) noexcept
{
using std::swap;
swap(type_, other.type_);
swap(offset_, other.offset_);
swap(length_, other.length_);
swap(url_, other.url_);
swap(user_, other.user_);
}
const MessageEntity& MessageEntity::operator=(MessageEntity other)
{
swap(other);
return *this;
} }
MessageEntity::Type messageEntityTypeFromString(const std::string& str) MessageEntity::Type messageEntityTypeFromString(const std::string& str)
@ -109,17 +87,17 @@ MessageEntity::Type messageEntityTypeFromString(const std::string& str)
throw std::invalid_argument("Unknown message entity type"); throw std::invalid_argument("Unknown message entity type");
} }
////////////////////////////////////////////////////////////////
Message::Message() Message::Message()
: id_(-1) : id_(-1),
deleteChatPhoto_(false),
groupChatCreated_(false),
superGroupChatCreated_(false),
channelChatCreated_(false)
{ {
} }
Message::Message(const Message&) = default;
Message::Message(Message&&) = default;
Message::~Message() = default;
int Message::getId() const int Message::getId() const
{ {
return id_; return id_;
@ -130,14 +108,14 @@ void Message::setId(int id)
id_ = id; id_ = id;
} }
const UserPtr Message::getFrom() const const boost::optional<User>& Message::getFrom() const
{ {
return from_; return from_;
} }
void Message::setFrom(UserPtr from) void Message::setFrom(optional<User> from)
{ {
from_ = from; from_ = std::move(from);
} }
time_t Message::getDate() const time_t Message::getDate() const
@ -155,42 +133,42 @@ const Chat& Message::getChat() const
return chat_; return chat_;
} }
void Message::setChat(const Chat& chat) void Message::setChat(Chat chat)
{ {
chat_ = chat; chat_ = std::move(chat);
} }
const UserPtr Message::getForwardFrom() const const optional<User>& Message::getForwardFrom() const
{ {
return forwardFrom_; return forwardFrom_;
} }
void Message::setForwardFrom(UserPtr forwardFrom) void Message::setForwardFrom(optional<User> forwardFrom)
{ {
forwardFrom_ = forwardFrom; forwardFrom_ = std::move(forwardFrom);
} }
const ChatPtr Message::getForwardFromChat() const const optional<Chat>& Message::getForwardFromChat() const
{ {
return forwardFromChat_; return forwardFromChat_;
} }
void Message::setForwardFromChat(ChatPtr forwardFromChat) void Message::setForwardFromChat(optional<Chat> forwardFromChat)
{ {
forwardFromChat_ = forwardFromChat; forwardFromChat_ = std::move(forwardFromChat);
} }
time_t Message::getForwardDate() const const optional<time_t>& Message::getForwardDate() const
{ {
return forwardDate_; return forwardDate_;
} }
void Message::setForwardDate(time_t forwardDate) void Message::setForwardDate(optional<time_t> forwardDate)
{ {
forwardDate_ = forwardDate; forwardDate_ = forwardDate;
} }
const MessagePtr Message::getReplyToMessage() const MessagePtr Message::getReplyToMessage() const
{ {
return replyToMessage_; return replyToMessage_;
} }
@ -200,94 +178,94 @@ void Message::setReplyToMessage(MessagePtr replyToMessage)
replyToMessage_ = replyToMessage; replyToMessage_ = replyToMessage;
} }
time_t Message::getEditDate() const const optional<time_t>& Message::getEditDate() const
{ {
return editDate_; return editDate_;
} }
void Message::setEditDate(time_t editDate) void Message::setEditDate(optional<time_t> editDate)
{ {
editDate_ = editDate; editDate_ = editDate;
} }
const std::string& Message::getText() const const optional<std::string>& Message::getText() const
{ {
return text_; return text_;
} }
void Message::setText(const std::string& text) void Message::setText(optional<std::string> text)
{ {
text_ = text; text_ = std::move(text);
} }
const MessageEntities& Message::getEntities() const const optional<MessageEntities>& Message::getEntities() const
{ {
return entities_; return entities_;
} }
void Message::setEntities(MessageEntities&& entities) void Message::setEntities(optional<MessageEntities> entities)
{ {
entities_ = entities; entities_ = std::move(entities);
} }
const AttachmentPtr Message::getAttachment() const const optional<Attachment>& Message::getAttachment() const
{ {
return attachment_; return attachment_;
} }
void Message::setAttachment(AttachmentPtr attachment) void Message::setAttachment(optional<Attachment> attachment)
{ {
attachment_ = attachment; attachment_ = std::move(attachment);
} }
const std::string& Message::getCaption() const const optional<std::string>& Message::getCaption() const
{ {
return caption_; return caption_;
} }
void Message::setCaption(const std::string& caption) void Message::setCaption(optional<std::string> caption)
{ {
caption_ = caption; caption_ = std::move(caption);
} }
const UserPtr Message::getNewChatMember() const const optional<User>& Message::getNewChatMember() const
{ {
return newChatMember_; return newChatMember_;
} }
void Message::setNewChatMember(UserPtr newChatMember) void Message::setNewChatMember(optional<User> newChatMember)
{ {
newChatMember_ = newChatMember; newChatMember_ = std::move(newChatMember);
} }
const UserPtr Message::getLeftChatMember() const const optional<User>& Message::getLeftChatMember() const
{ {
return leftChatMember_; return leftChatMember_;
} }
void Message::setLeftChatMember(UserPtr leftChatMember) void Message::setLeftChatMember(optional<User> leftChatMember)
{ {
leftChatMember_ = leftChatMember; leftChatMember_ = std::move(leftChatMember);
} }
const std::string& Message::getNewChatTitle() const const optional<std::string>& Message::getNewChatTitle() const
{ {
return newChatTitle_; return newChatTitle_;
} }
void Message::setNewChatTitle(const std::string& newChatTitle) void Message::setNewChatTitle(optional<std::string> newChatTitle)
{ {
newChatTitle_ = newChatTitle; newChatTitle_ = std::move(newChatTitle);
} }
const PhotoSizeArrayPtr Message::getNewChatPhoto() const const optional<PhotoSizeArray> Message::getNewChatPhoto() const
{ {
return newChatPhoto_; return newChatPhoto_;
} }
void Message::setNewChatPhoto(PhotoSizeArrayPtr newChatPhoto) void Message::setNewChatPhoto(optional<PhotoSizeArray> newChatPhoto)
{ {
newChatPhoto_ = newChatPhoto; newChatPhoto_ = std::move(newChatPhoto);
} }
bool Message::isDeleteChatPhoto() const bool Message::isDeleteChatPhoto() const
@ -330,27 +308,27 @@ void Message::setChannelChatCreated(bool channelChatCreated)
channelChatCreated_ = channelChatCreated; channelChatCreated_ = channelChatCreated;
} }
std::int64_t Message::getMigrateToChatId() const const optional<std::int64_t>& Message::getMigrateToChatId() const
{ {
return migrateToChatId_; return migrateToChatId_;
} }
void Message::setMigrateToChatId(std::int64_t migrateToChatId) void Message::setMigrateToChatId(optional<std::int64_t> migrateToChatId)
{ {
migrateToChatId_ = migrateToChatId; migrateToChatId_ = migrateToChatId;
} }
std::int64_t Message::getMigrateFromChatId() const const optional<std::int64_t>& Message::getMigrateFromChatId() const
{ {
return migrateFromChatId_; return migrateFromChatId_;
} }
void Message::setMigrateFromChatId(std::int64_t migrateFromChatId) void Message::setMigrateFromChatId(optional<std::int64_t> migrateFromChatId)
{ {
migrateFromChatId_ = migrateFromChatId; migrateFromChatId_ = migrateFromChatId;
} }
const MessagePtr Message::getPinnedMessage() const MessagePtr Message::getPinnedMessage() const
{ {
return pinnedMessage_; return pinnedMessage_;
} }
@ -360,44 +338,4 @@ void Message::setPinnedMessage(MessagePtr pinnedMessage)
pinnedMessage_ = pinnedMessage; pinnedMessage_ = pinnedMessage;
} }
void Message::swap(Message& other) noexcept
{
using std::swap;
swap(id_, other.id_);
swap(from_, other.from_);
swap(date_, other.date_);
swap(chat_, other.chat_);
swap(forwardFrom_, other.forwardFrom_);
swap(forwardFromChat_, other.forwardFromChat_);
swap(forwardDate_, other.forwardDate_);
swap(replyToMessage_, other.replyToMessage_);
swap(editDate_, other.editDate_);
swap(text_, other.text_);
swap(entities_, other.entities_);
swap(attachment_, other.attachment_);
swap(caption_, other.caption_);
swap(newChatMember_, other.newChatMember_);
swap(leftChatMember_, other.leftChatMember_);
swap(newChatTitle_, other.newChatTitle_);
swap(newChatPhoto_, other.newChatPhoto_);
swap(deleteChatPhoto_, other.deleteChatPhoto_);
swap(groupChatCreated_, other.groupChatCreated_);
swap(superGroupChatCreated_, other.superGroupChatCreated_);
swap(channelChatCreated_, other.channelChatCreated_);
swap(migrateToChatId_, other.migrateToChatId_);
swap(migrateFromChatId_, other.migrateFromChatId_);
swap(pinnedMessage_, other.pinnedMessage_);
}
const Message& Message::operator=(Message other) noexcept
{
swap(other);
return *this;
}
void swap(Message& lhs, Message& rhs)
{
lhs.swap(rhs);
}
} }

View file

@ -20,12 +20,6 @@ ChatId::ChatId(const std::string& str)
{ {
} }
ChatId::ChatId(const ChatId& other) = default;
ChatId::ChatId(ChatId&& other) = default;
ChatId::~ChatId() = default;
ChatId::Type ChatId::getType() const ChatId::Type ChatId::getType() const
{ {
return type_; return type_;
@ -126,12 +120,6 @@ Photo::Photo(const Url& url)
{ {
} }
Photo::Photo(const Photo& other) = default;
Photo::Photo(Photo&& other) = default;
Photo::~Photo() = default;
Photo::Type Photo::getType() const Photo::Type Photo::getType() const
{ {
return type_; return type_;

View file

@ -1,17 +1,15 @@
#include <telebotxx/Update.hpp> #include <telebotxx/Update.hpp>
#include <boost/variant.hpp>
namespace telebotxx { namespace telebotxx {
Update::Update(int id, Type type) Update::Update(int id, Type type, std::unique_ptr<Message> message)
: id_(id), : id_(id),
updateType_(type) type_(type),
value_(std::move(message))
{ {
} }
Update::Update(const Update&) = default;
Update::Update(Update&&) = default;
Update::~Update() = default;
int Update::getId() const int Update::getId() const
{ {
return id_; return id_;
@ -19,66 +17,12 @@ int Update::getId() const
Update::Type Update::getType() const Update::Type Update::getType() const
{ {
return updateType_; return type_;
} }
void Update::swap(Update& other) noexcept MessagePtr Update::getMessage() const
{ {
using std::swap; return boost::get<MessagePtr>(value_);
swap(id_, other.id_);
swap(updateType_, other.updateType_);
}
////////////////////////////////////////////////////////////////
MessageUpdate::MessageUpdate(int id, const Message& message)
: Update(id, Type::Message),
message_(message)
{
}
MessageUpdate::MessageUpdate(const MessageUpdate&) = default;
MessageUpdate::MessageUpdate(MessageUpdate&&) = default;
MessageUpdate::~MessageUpdate() = default;
const Message& MessageUpdate::getMessage() const
{
return message_;
}
void MessageUpdate::swap(MessageUpdate& other) noexcept
{
using std::swap;
Update::swap(other);
swap(message_, other.message_);
}
const MessageUpdate& MessageUpdate::operator=(MessageUpdate other)
{
swap(other);
return *this;
}
////////////////////////////////////////////////////////////////
EditedMessageUpdate::EditedMessageUpdate(int id, const Message& message)
: MessageUpdate(id, message)
{
}
EditedMessageUpdate::EditedMessageUpdate(const EditedMessageUpdate&) = default;
EditedMessageUpdate::EditedMessageUpdate(EditedMessageUpdate&&) = default;
EditedMessageUpdate::~EditedMessageUpdate() = default;
void EditedMessageUpdate::swap(EditedMessageUpdate& other) noexcept
{
MessageUpdate::swap(other);
}
const EditedMessageUpdate& EditedMessageUpdate::operator=(EditedMessageUpdate other)
{
swap(other);
return *this;
} }
} }

View file

@ -8,12 +8,6 @@ User::User()
{ {
} }
User::User(const User&) = default;
User::User(User&&) = default;
User::~User() = default;
int User::getId() const int User::getId() const
{ {
return id_; return id_;
@ -29,52 +23,42 @@ const std::string& User::getFirstName() const
return firstName_; return firstName_;
} }
void User::setFirstName(const std::string& firstName) void User::setFirstName(std::string firstName)
{ {
firstName_ = firstName; firstName_ = std::move(firstName);
} }
const std::string& User::getLastName() const const optional<std::string>& User::getLastName() const
{ {
return lastName_; return lastName_;
} }
void User::setLastName(const std::string& lastName) void User::setLastName(optional<std::string> lastName)
{ {
lastName_ = lastName; lastName_ = std::move(lastName);
} }
const std::string& User::getUsername() const const optional<std::string>& User::getUsername() const
{ {
return username_; return username_;
} }
void User::setUsername(const std::string& username) void User::setUsername(optional<std::string> username)
{ {
username_ = username; username_ = std::move(username);
} }
const std::string User::toString() const const std::string User::toString() const
{ {
std::stringstream ss; std::stringstream ss;
ss << firstName_ << " " << lastName_ << " (@" << username_ << ")"; ss << firstName_;
if (lastName_)
ss << " " << *lastName_;
if (username_)
ss << " (@" << *username_ << ")";
return ss.str(); return ss.str();
} }
void User::swap(User& other) noexcept
{
std::swap(id_, other.id_);
firstName_.swap(other.firstName_);
lastName_.swap(other.lastName_);
username_.swap(other.username_);
}
const User& User::operator=(User other)
{
swap(other);
return *this;
}
std::ostream& operator<<(std::ostream& os, const User& user) std::ostream& operator<<(std::ostream& os, const User& user)
{ {
os << user.toString(); os << user.toString();

View file

@ -9,7 +9,7 @@ include(${CMAKE_SOURCE_DIR}/cmake/RequireCXX14.cmake)
RequireCXX14() RequireCXX14()
add_definitions(-DBOOST_TEST_DYN_LINK) add_definitions(-DBOOST_TEST_DYN_LINK)
find_package(Boost REQUIRED COMPONENTS unit_test_framework system) find_package(Boost 1.56 REQUIRED COMPONENTS unit_test_framework system)
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
# Add required compiler flags # Add required compiler flags

View file

@ -86,7 +86,7 @@ struct TestConfig
BOOST_GLOBAL_FIXTURE(TestConfig); BOOST_GLOBAL_FIXTURE(TestConfig);
BOOST_AUTO_TEST_SUITE(TestBotApi) BOOST_AUTO_TEST_SUITE(TestSend)
BOOST_AUTO_TEST_CASE(DefaultConstructor) BOOST_AUTO_TEST_CASE(DefaultConstructor)
{ {
@ -214,6 +214,10 @@ BOOST_AUTO_TEST_SUITE(TestBotApi)
)); ));
} }
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE(TestParse)
BOOST_AUTO_TEST_CASE(GetUpdates) BOOST_AUTO_TEST_CASE(GetUpdates)
{ {
PRINT_TESTNAME; PRINT_TESTNAME;
@ -222,15 +226,22 @@ BOOST_AUTO_TEST_SUITE(TestBotApi)
BOOST_REQUIRE_NO_THROW(updates = bot->getUpdates()); BOOST_REQUIRE_NO_THROW(updates = bot->getUpdates());
for (auto update : updates) for (auto update : updates)
{ {
if (update->getType() == Update::Type::Message) switch (update.getType())
{ {
auto& message = std::dynamic_pointer_cast<MessageUpdate>(update)->getMessage(); case Update::Type::Message:
if (message.getFrom()) case Update::Type::EditedMessage:
std::cout << *message.getFrom() << ": "; case Update::Type::ChannelPost:
std::cout << message.getText() << std::endl; 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() BOOST_AUTO_TEST_SUITE_END()

View file

@ -17,15 +17,15 @@ BOOST_AUTO_TEST_SUITE(TestUser)
PRINT_TESTNAME; PRINT_TESTNAME;
User other; User other;
other.setId(1); other.setId(1);
other.setFirstName("John"); other.setFirstName(std::string("John"));
other.setLastName("Smith"); other.setLastName(std::string("Smith"));
other.setUsername("john_smith"); other.setUsername(std::string("john_smith"));
std::unique_ptr<User> user; std::unique_ptr<User> user;
BOOST_REQUIRE_NO_THROW(user.reset(new User(other))); BOOST_REQUIRE_NO_THROW(user.reset(new User(other)));
BOOST_REQUIRE_EQUAL(user->getId(), 1); BOOST_REQUIRE_EQUAL(user->getId(), 1);
BOOST_REQUIRE_EQUAL(user->getFirstName(), "John"); BOOST_REQUIRE_EQUAL(user->getFirstName(), "John");
BOOST_REQUIRE_EQUAL(user->getLastName(), "Smith"); BOOST_REQUIRE_EQUAL(*user->getLastName(), "Smith");
BOOST_REQUIRE_EQUAL(user->getUsername(), "john_smith"); BOOST_REQUIRE_EQUAL(*user->getUsername(), "john_smith");
} }
BOOST_AUTO_TEST_CASE(MoveConstructor) BOOST_AUTO_TEST_CASE(MoveConstructor)
@ -33,15 +33,15 @@ BOOST_AUTO_TEST_SUITE(TestUser)
PRINT_TESTNAME; PRINT_TESTNAME;
User other; User other;
other.setId(1); other.setId(1);
other.setFirstName("John"); other.setFirstName(std::string("John"));
other.setLastName("Smith"); other.setLastName(std::string("Smith"));
other.setUsername("john_smith"); other.setUsername(std::string("john_smith"));
std::unique_ptr<User> user; std::unique_ptr<User> user;
BOOST_REQUIRE_NO_THROW(user.reset(new User(std::move(other)))); BOOST_REQUIRE_NO_THROW(user.reset(new User(std::move(other))));
BOOST_REQUIRE_EQUAL(user->getId(), 1); BOOST_REQUIRE_EQUAL(user->getId(), 1);
BOOST_REQUIRE_EQUAL(user->getFirstName(), "John"); BOOST_REQUIRE_EQUAL(user->getFirstName(), "John");
BOOST_REQUIRE_EQUAL(user->getLastName(), "Smith"); BOOST_REQUIRE_EQUAL(*user->getLastName(), "Smith");
BOOST_REQUIRE_EQUAL(user->getUsername(), "john_smith"); BOOST_REQUIRE_EQUAL(*user->getUsername(), "john_smith");
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()