Used boost::optional for optional fields.

Updates and attachments hierarchy replaced with Union-like classes.
Changes in JSON parsing for RVO/move-semantics.
This commit is contained in:
Kirill Kirilenko 2017-02-19 16:09:13 +03:00
parent 79ea1a08a1
commit 9a607eef8c
20 changed files with 605 additions and 962 deletions

View file

@ -1,13 +1,133 @@
#ifndef TELEBOTXX_ATTACHMENT_HPP
#define TELEBOTXX_ATTACHMENT_HPP
#include "Optional.hpp"
#include <string>
#include <ctime>
#include <memory>
#include <vector>
#include <memory>
#include <boost/variant/variant.hpp>
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
{
public:
@ -25,194 +145,23 @@ public:
Venue
};
Attachment(Type type);
Attachment(const Attachment&);
Attachment(Attachment&&);
virtual ~Attachment() = 0;
Attachment(PhotoSizeArray);
Attachment(Audio);
Attachment(Document);
Attachment(Sticker);
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:
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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,30 +1,9 @@
#include <telebotxx/Attachment.hpp>
#include <boost/variant.hpp>
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()
: width_(-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
{
return fileId_;
@ -68,81 +41,24 @@ void PhotoSize::setHeight(int height)
height_ = height;
}
int PhotoSize::getFileSize() const
const optional<int>& PhotoSize::getFileSize() const
{
return fileSize_;
}
void PhotoSize::setFileSize(int fileSize)
void PhotoSize::setFileSize(optional<int> 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()
: Attachment(Type::Audio),
duration_(-1),
: duration_(-1),
fileSize_(-1)
{
}
Audio::Audio(const Audio&) = default;
Audio::Audio(Audio&&) = default;
Audio::~Audio() = default;
const std::string& Audio::getFileId() const
{
return fileId_;
@ -163,159 +79,110 @@ void Audio::setDuration(int duration)
duration_ = duration;
}
const std::string& Audio::getPerformer() const
const optional<std::string>& Audio::getPerformer() const
{
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_;
}
void Audio::setTitle(const std::string& title)
void Audio::setTitle(optional<std::string> title)
{
title_ = title;
}
const std::string& Audio::getMimeType() const
const optional<std::string>& Audio::getMimeType() const
{
return mimeType_;
}
void Audio::setMimeType(const std::string& mimeType)
void Audio::setMimeType(optional<std::string> mimeType)
{
mimeType_ = mimeType;
}
int Audio::getFileSize() const
const optional<int>& Audio::getFileSize() const
{
return fileSize_;
}
void Audio::setFileSize(int fileSize)
void Audio::setFileSize(optional<int> 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()
: 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
{
return fileId_;
}
void Document::setFileId(const std::string& fileId)
void Document::setFileId(std::string fileId)
{
fileId_ = fileId;
}
const PhotoSizePtr Document::getThumb() const
const optional<PhotoSize>& Document::getThumb() const
{
return thumb_;
}
void Document::setThumb(const PhotoSizePtr& thumb)
void Document::setThumb(optional<PhotoSize> thumb)
{
thumb_ = thumb;
}
const std::string& Document::getFileName() const
const optional<std::string>& Document::getFileName() const
{
return fileName_;
}
void Document::setFileName(const std::string& fileName)
void Document::setFileName(optional<std::string> fileName)
{
fileName_ = fileName;
}
const std::string& Document::getMimeType() const
const optional<std::string>& Document::getMimeType() const
{
return mimeType_;
}
void Document::setMimeType(const std::string& mimeType)
void Document::setMimeType(optional<std::string> mimeType)
{
mimeType_ = mimeType;
}
int Document::getFileSize() const
const optional<int>& Document::getFileSize() const
{
return fileSize_;
}
void Document::setFileSize(int fileSize)
void Document::setFileSize(optional<int> 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()
: 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
{
return fileId_;
@ -346,79 +213,81 @@ void Sticker::setHeight(int height)
height_ = height;
}
const PhotoSizePtr Sticker::getThumb() const
const optional<PhotoSize>& Sticker::getThumb() const
{
return thumb_;
}
void Sticker::setThumb(const PhotoSizePtr& thumb)
void Sticker::setThumb(optional<PhotoSize> thumb)
{
thumb_ = thumb;
}
const std::string& Sticker::getEmoji() const
const optional<std::string>& Sticker::getEmoji() const
{
return emoji_;
}
void Sticker::setEmoji(const std::string& emoji)
void Sticker::setEmoji(optional<std::string> emoji)
{
emoji_ = emoji;
}
int Sticker::getFileSize() const
const optional<int>& Sticker::getFileSize() const
{
return fileSize_;
}
void Sticker::setFileSize(int fileSize)
void Sticker::setFileSize(optional<int> 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());
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)
@ -133,7 +133,7 @@ public:
doc.Parse(response.c_str());
checkResponse(doc);
return *parseUpdates(doc, "result", REQUIRED);
return parseUpdates(doc, "result");
}
std::string getTelegramMainUrl() const

View file

@ -5,7 +5,7 @@ message(STATUS "Configuring telebotxx")
include(${CMAKE_SOURCE_DIR}/cmake/RequireCXX14.cmake)
RequireCXX14()
find_package(Boost REQUIRED)
find_package(Boost 1.56 REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
# 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
{
return id_;
@ -36,42 +30,42 @@ void Chat::setType(Chat::Type type)
type_ = type;
}
const std::string& Chat::getTitle() const
const optional<std::string>& Chat::getTitle() const
{
return title_;
}
void Chat::setTitle(const std::string& title)
void Chat::setTitle(optional<std::string> title)
{
title_ = title;
}
const std::string& Chat::getUsername() const
const optional<std::string>& Chat::getUsername() const
{
return username_;
}
void Chat::setUsername(const std::string& username)
void Chat::setUsername(optional<std::string> username)
{
username_ = username;
}
const std::string& Chat::getFirstName() const
const optional<std::string>& Chat::getFirstName() const
{
return firstName_;
}
void Chat::setFirstName(const std::string& firstName)
void Chat::setFirstName(optional<std::string> firstName)
{
firstName_ = firstName;
}
const std::string& Chat::getLastName() const
const optional<std::string>& Chat::getLastName() const
{
return lastName_;
}
void Chat::setLastName(const std::string& lastName)
void Chat::setLastName(optional<std::string> lastName)
{
lastName_ = lastName;
}
@ -86,29 +80,6 @@ void Chat::setAllAdmins(bool 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)
{
if (str == "private")

View file

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

View file

@ -5,6 +5,8 @@
#include <telebotxx/Message.hpp>
#include <telebotxx/Update.hpp>
#include <telebotxx/User.hpp>
#include <telebotxx/Optional.hpp>
#include <telebotxx/Exception.hpp>
#include <memory>
@ -15,19 +17,58 @@ namespace telebotxx {
const bool REQUIRED = true;
const bool OPTIONAL = false;
/// \brief Parse JSON object to Chat
/// \param parent reference to parent JSON object
/// \param name field with Chat object
/// \param required REQUIRED or OPTIONAL
/// \return pointer to Chat
std::unique_ptr<Chat> parseChat(const rapidjson::Value& parent, const char* name, bool required);
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> 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
/// \param parent reference to parent JSON object
/// \param name field with Document object
/// \param required REQUIRED or OPTIONAL
/// \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
/// \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
/// \param parent reference to parent JSON object
/// \param name field with array of Update objects
/// \param required REQUIRED or OPTIONAL
/// \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
///

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
{
return type_;
@ -45,40 +39,24 @@ void MessageEntity::setLength(size_t length)
length_ = length;
}
const std::string& MessageEntity::getUrl() const
const optional<std::string>& MessageEntity::getUrl() const
{
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_;
}
void MessageEntity::setUser(const User& user)
void MessageEntity::setUser(User user)
{
user_ = 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;
user_ = std::move(user);
}
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");
}
////////////////////////////////////////////////////////////////
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
{
return id_;
@ -130,14 +108,14 @@ void Message::setId(int id)
id_ = id;
}
const UserPtr Message::getFrom() const
const boost::optional<User>& Message::getFrom() const
{
return from_;
}
void Message::setFrom(UserPtr from)
void Message::setFrom(optional<User> from)
{
from_ = from;
from_ = std::move(from);
}
time_t Message::getDate() const
@ -155,42 +133,42 @@ const Chat& Message::getChat() const
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_;
}
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_;
}
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_;
}
void Message::setForwardDate(time_t forwardDate)
void Message::setForwardDate(optional<time_t> forwardDate)
{
forwardDate_ = forwardDate;
}
const MessagePtr Message::getReplyToMessage() const
MessagePtr Message::getReplyToMessage() const
{
return replyToMessage_;
}
@ -200,94 +178,94 @@ void Message::setReplyToMessage(MessagePtr replyToMessage)
replyToMessage_ = replyToMessage;
}
time_t Message::getEditDate() const
const optional<time_t>& Message::getEditDate() const
{
return editDate_;
}
void Message::setEditDate(time_t editDate)
void Message::setEditDate(optional<time_t> editDate)
{
editDate_ = editDate;
}
const std::string& Message::getText() const
const optional<std::string>& Message::getText() const
{
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_;
}
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_;
}
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_;
}
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_;
}
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_;
}
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_;
}
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_;
}
void Message::setNewChatPhoto(PhotoSizeArrayPtr newChatPhoto)
void Message::setNewChatPhoto(optional<PhotoSizeArray> newChatPhoto)
{
newChatPhoto_ = newChatPhoto;
newChatPhoto_ = std::move(newChatPhoto);
}
bool Message::isDeleteChatPhoto() const
@ -330,27 +308,27 @@ void Message::setChannelChatCreated(bool channelChatCreated)
channelChatCreated_ = channelChatCreated;
}
std::int64_t Message::getMigrateToChatId() const
const optional<std::int64_t>& Message::getMigrateToChatId() const
{
return migrateToChatId_;
}
void Message::setMigrateToChatId(std::int64_t migrateToChatId)
void Message::setMigrateToChatId(optional<std::int64_t> migrateToChatId)
{
migrateToChatId_ = migrateToChatId;
}
std::int64_t Message::getMigrateFromChatId() const
const optional<std::int64_t>& Message::getMigrateFromChatId() const
{
return migrateFromChatId_;
}
void Message::setMigrateFromChatId(std::int64_t migrateFromChatId)
void Message::setMigrateFromChatId(optional<std::int64_t> migrateFromChatId)
{
migrateFromChatId_ = migrateFromChatId;
}
const MessagePtr Message::getPinnedMessage() const
MessagePtr Message::getPinnedMessage() const
{
return pinnedMessage_;
}
@ -360,44 +338,4 @@ void Message::setPinnedMessage(MessagePtr 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,10 +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
{
return type_;
@ -124,10 +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
{
return type_;

View file

@ -1,66 +1,28 @@
#include <telebotxx/Update.hpp>
#include <boost/variant.hpp>
namespace telebotxx {
Update::Update(int id, Type type)
Update::Update(int id, Type type, std::unique_ptr<Message> message)
: 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
{
return id_;
}
Update::Type Update::getType() const
{
return updateType_;
}
void Update::swap(Update& other) noexcept
{
using std::swap;
swap(id_, other.id_);
swap(updateType_, other.updateType_);
}
////////////////////////////////////////////////////////////////
MessageUpdate::MessageUpdate(int id, MessageType type, const Message& message)
: Update(id, Type::Message), type_(type), message_(message)
{
}
MessageUpdate::MessageUpdate(const MessageUpdate&) = default;
MessageUpdate::MessageUpdate(MessageUpdate&&) = default;
MessageUpdate::~MessageUpdate() = default;
MessageUpdate::MessageType MessageUpdate::getMessageType() const
{
return type_;
}
const Message& MessageUpdate::getMessage() const
MessagePtr Update::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;
return boost::get<MessagePtr>(value_);
}
}

View file

@ -8,12 +8,6 @@ User::User()
{
}
User::User(const User&) = default;
User::User(User&&) = default;
User::~User() = default;
int User::getId() const
{
return id_;
@ -29,52 +23,42 @@ const std::string& User::getFirstName() const
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_;
}
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_;
}
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
{
std::stringstream ss;
ss << firstName_ << " " << lastName_ << " (@" << username_ << ")";
ss << firstName_;
if (lastName_)
ss << " " << *lastName_;
if (username_)
ss << " (@" << *username_ << ")";
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)
{
os << user.toString();

View file

@ -86,7 +86,7 @@ struct TestConfig
BOOST_GLOBAL_FIXTURE(TestConfig);
BOOST_AUTO_TEST_SUITE(TestBotApi)
BOOST_AUTO_TEST_SUITE(TestSend)
BOOST_AUTO_TEST_CASE(DefaultConstructor)
{
@ -198,6 +198,10 @@ BOOST_AUTO_TEST_SUITE(TestBotApi)
));
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE(TestParse)
BOOST_AUTO_TEST_CASE(GetUpdates)
{
PRINT_TESTNAME;
@ -206,19 +210,22 @@ BOOST_AUTO_TEST_SUITE(TestBotApi)
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 = std::dynamic_pointer_cast<MessageUpdate>(update)->getMessage();
if (message.getFrom())
std::cout << *message.getFrom() << ": ";
std::cout << message.getText() << std::endl;
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

@ -17,15 +17,15 @@ BOOST_AUTO_TEST_SUITE(TestUser)
PRINT_TESTNAME;
User other;
other.setId(1);
other.setFirstName("John");
other.setLastName("Smith");
other.setUsername("john_smith");
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_REQUIRE_EQUAL(*user->getLastName(), "Smith");
BOOST_REQUIRE_EQUAL(*user->getUsername(), "john_smith");
}
BOOST_AUTO_TEST_CASE(MoveConstructor)
@ -33,15 +33,15 @@ BOOST_AUTO_TEST_SUITE(TestUser)
PRINT_TESTNAME;
User other;
other.setId(1);
other.setFirstName("John");
other.setLastName("Smith");
other.setUsername("john_smith");
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_REQUIRE_EQUAL(*user->getLastName(), "Smith");
BOOST_REQUIRE_EQUAL(*user->getUsername(), "john_smith");
}
BOOST_AUTO_TEST_SUITE_END()