mirror of
https://github.com/UltraCoderRU/telebotxx.git
synced 2026-01-27 19:55:14 +00:00
Rewritten sendPhoto functions, which are now variadic templated.
This commit is contained in:
parent
d5e6a89cad
commit
adb0630961
8 changed files with 337 additions and 21 deletions
|
|
@ -5,6 +5,7 @@
|
|||
#include "Message.hpp"
|
||||
#include "Update.hpp"
|
||||
#include "SendMessageRequest.hpp"
|
||||
#include "SendPhotoRequest.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
|
@ -57,18 +58,23 @@ namespace telebotxx
|
|||
}
|
||||
|
||||
/// \brief Send image
|
||||
/// \param [in] chat chat identifier
|
||||
/// \param [in] filename image location
|
||||
/// \param [in] caption optional photo caption
|
||||
/// \param [in] chatId chat identifier
|
||||
/// \param [in] photo photo
|
||||
/// \return Message object, recieved from the server
|
||||
Message sendPhoto(const std::string& chat, const std::string& filename, const std::string& caption = "");
|
||||
Message sendPhoto(ChatId&& chatId, Photo&& photo);
|
||||
|
||||
/// \brief Send image by URL
|
||||
/// \param [in] chat chat identifier
|
||||
/// \param [in] url image URL
|
||||
/// \param [in] caption optional photo caption
|
||||
/// \brief Send image
|
||||
/// \param [in] chatId chat identifier
|
||||
/// \param [in] photo photo
|
||||
/// \param [in] args parameters
|
||||
/// \return Message object, recieved from the server
|
||||
Message sendPhotoUrl(const std::string& chat, const std::string& url, const std::string& caption = "");
|
||||
template<typename... Ts>
|
||||
Message sendPhoto(ChatId&& chatId, Photo&& photo, Ts&&... args)
|
||||
{
|
||||
SendPhotoRequest request(getTelegramMainUrl(), std::forward<ChatId>(chatId), std::forward<Photo>(photo));
|
||||
setRequestOption(request, std::forward<Ts>(args)...);
|
||||
return request.execute();
|
||||
}
|
||||
|
||||
/// \brief Get updates using long polling
|
||||
/// \param offset identifier of the first update to be returned
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define TELEBOTXX_REQUEST_OPTIONS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace telebotxx
|
||||
{
|
||||
|
|
@ -64,6 +65,20 @@ namespace telebotxx
|
|||
int id_;
|
||||
};
|
||||
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
Buffer(const char* buffer, std::size_t size, const std::string& filename);
|
||||
explicit Buffer(const std::vector<char>& data, const std::string& filename);
|
||||
const char* data() const;
|
||||
const std::size_t size() const;
|
||||
const std::string filename() const;
|
||||
private:
|
||||
const char* data_;
|
||||
std::size_t size_;
|
||||
std::string filename_;
|
||||
};
|
||||
|
||||
class File
|
||||
{
|
||||
public:
|
||||
|
|
@ -86,20 +101,27 @@ namespace telebotxx
|
|||
{
|
||||
public:
|
||||
explicit Photo(int id);
|
||||
explicit Photo(const Buffer&);
|
||||
explicit Photo(const File&);
|
||||
explicit Photo(const Url&);
|
||||
Photo(const Photo&);
|
||||
Photo(Photo&&);
|
||||
~Photo();
|
||||
|
||||
enum class Type { File, Url, Id };
|
||||
enum class Type { Id, Buffer, File, Url};
|
||||
Type getType() const;
|
||||
|
||||
int getId() const;
|
||||
const Buffer& getBuffer() const;
|
||||
const File& getFile() const;
|
||||
const Url& getUrl() const;
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
union
|
||||
{
|
||||
int id_;
|
||||
Buffer buffer_;
|
||||
File file_;
|
||||
Url url_;
|
||||
};
|
||||
|
|
|
|||
35
include/telebotxx/SendPhotoRequest.hpp
Normal file
35
include/telebotxx/SendPhotoRequest.hpp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef TELEBOTXX_SEND_PHOTO_REQUEST_HPP
|
||||
#define TELEBOTXX_SEND_PHOTO_REQUEST_HPP
|
||||
|
||||
#include <telebotxx/RequestOptions.hpp>
|
||||
#include <telebotxx/Message.hpp>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace telebotxx
|
||||
{
|
||||
class SendPhotoRequest
|
||||
{
|
||||
public:
|
||||
SendPhotoRequest(const std::string& telegramMainUrl, const ChatId& chat, const Photo& photo);
|
||||
~SendPhotoRequest();
|
||||
|
||||
void setCaption(const Caption& caption);
|
||||
void setDisableNotification(const DisableNotification& disableNotification);
|
||||
void setReplyToMessageId(const ReplyTo& replyToMessageId);
|
||||
void setOption(const Caption& caption);
|
||||
void setOption(const DisableNotification& disableNotification);
|
||||
void setOption(const ReplyTo& replyToMessageId);
|
||||
|
||||
Message execute();
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TELEBOTXX_SEND_PHOTO_REQUEST_HPP
|
||||
|
|
@ -166,14 +166,10 @@ Message BotApi::sendMessage(ChatId&& chatId, Text&& text)
|
|||
return request.execute();
|
||||
}
|
||||
|
||||
Message BotApi::sendPhoto(const std::string& chat, const std::string& filename, const std::string& caption)
|
||||
Message BotApi::sendPhoto(ChatId&& chatId, Photo&& photo)
|
||||
{
|
||||
return impl_->sendPhoto(chat, filename, caption);
|
||||
}
|
||||
|
||||
Message BotApi::sendPhotoUrl(const std::string& chat, const std::string& url, const std::string& caption)
|
||||
{
|
||||
return impl_->sendPhotoUrl(chat, url, caption);
|
||||
SendPhotoRequest request(getTelegramMainUrl(), std::forward<ChatId>(chatId), std::forward<Photo>(photo));
|
||||
return request.execute();
|
||||
}
|
||||
|
||||
Updates BotApi::getUpdates(int offset, unsigned short limit, unsigned int timeout)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ set(SOURCE_FILES Attachment.cpp
|
|||
User.cpp
|
||||
RequestOptions.cpp
|
||||
SendMessageRequest.cpp
|
||||
SendPhotoRequest.cpp
|
||||
)
|
||||
|
||||
add_library(telebotxx SHARED ${SOURCE_FILES})
|
||||
|
|
|
|||
|
|
@ -95,6 +95,33 @@ int ReplyTo::value() const
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
Buffer::Buffer(const char *buffer, std::size_t size, const std::string& filename)
|
||||
: data_(buffer), size_(size), filename_(filename)
|
||||
{
|
||||
}
|
||||
|
||||
Buffer::Buffer(const std::vector<char>& data, const std::string& filename)
|
||||
: data_(data.data()), size_(data.size()), filename_(filename)
|
||||
{
|
||||
}
|
||||
|
||||
const char* Buffer::data() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
const std::size_t Buffer::size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
const std::string Buffer::filename() const
|
||||
{
|
||||
return filename_;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
File::File(const std::string& filename)
|
||||
: filename_(filename)
|
||||
{
|
||||
|
|
@ -124,6 +151,11 @@ Photo::Photo(int id)
|
|||
{
|
||||
}
|
||||
|
||||
Photo::Photo(const Buffer& buffer)
|
||||
: type_(Type::Buffer), buffer_(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
Photo::Photo(const File& file)
|
||||
: type_(Type::File), file_(file)
|
||||
{
|
||||
|
|
@ -139,12 +171,38 @@ Photo::Photo(const Photo& other)
|
|||
{
|
||||
if (type_ == Type::Id)
|
||||
id_ = other.id_;
|
||||
else if (type_ == Type::Buffer)
|
||||
new(&buffer_) Buffer(other.buffer_);
|
||||
else if (type_ == Type::File)
|
||||
new(&file_) File(other.file_);
|
||||
else
|
||||
new(&url_) Url(other.url_);
|
||||
}
|
||||
|
||||
Photo::Photo(Photo&& other)
|
||||
{
|
||||
if (type_ == Type::Id)
|
||||
{
|
||||
id_ = other.id_;
|
||||
other.id_ = 0;
|
||||
}
|
||||
else if (type_ == Type::Buffer)
|
||||
{
|
||||
new(&buffer_) Buffer(std::move(other.buffer_));
|
||||
other.buffer_.~Buffer();
|
||||
}
|
||||
else if (type_ == Type::File)
|
||||
{
|
||||
new(&file_) File(std::move(other.file_));
|
||||
other.file_.~File();
|
||||
}
|
||||
else
|
||||
{
|
||||
new(&url_) Url(std::move(other.url_));
|
||||
other.url_.~Url();
|
||||
}
|
||||
}
|
||||
|
||||
Photo::~Photo()
|
||||
{
|
||||
if (type_ == Type::File)
|
||||
|
|
@ -156,4 +214,24 @@ Photo::~Photo()
|
|||
Photo::Type Photo::getType() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
}
|
||||
|
||||
int Photo::getId() const
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
|
||||
const Buffer& Photo::getBuffer() const
|
||||
{
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
const File& Photo::getFile() const
|
||||
{
|
||||
return file_;
|
||||
}
|
||||
|
||||
const Url& Photo::getUrl() const
|
||||
{
|
||||
return url_;
|
||||
}
|
||||
|
|
|
|||
137
src/SendPhotoRequest.cpp
Normal file
137
src/SendPhotoRequest.cpp
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
#include <telebotxx/SendPhotoRequest.hpp>
|
||||
|
||||
#include <telebotxx/Logging.hpp>
|
||||
#include "JsonObjects.hpp"
|
||||
|
||||
#include <cpr/cpr.h>
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/writer.h>
|
||||
|
||||
using namespace telebotxx;
|
||||
|
||||
class SendPhotoRequest::Impl
|
||||
{
|
||||
public:
|
||||
Impl(const std::string& telegramMainUrl, const ChatId& chat, const Photo& photo)
|
||||
: telegramMainUrl_(telegramMainUrl), chatId_(chat), photo_(photo)
|
||||
{
|
||||
}
|
||||
|
||||
void setCaption(const Caption& caption)
|
||||
{
|
||||
caption_ = caption;
|
||||
}
|
||||
|
||||
void setDisableNotification(const DisableNotification& disableNotification)
|
||||
{
|
||||
disableNotification_ = disableNotification;
|
||||
}
|
||||
|
||||
void setReplyToMessageId(const ReplyTo& replyToMessageId)
|
||||
{
|
||||
replyToMessageId_ = replyToMessageId;
|
||||
}
|
||||
|
||||
Message execute()
|
||||
{
|
||||
cpr::Multipart multipart{};
|
||||
|
||||
// Add chat_id
|
||||
if (chatId_.getType() == ChatId::Type::Id)
|
||||
multipart.parts.push_back({"chat_id", chatId_.getId()});
|
||||
else
|
||||
multipart.parts.push_back({"chat_id", chatId_.getUsername()});
|
||||
|
||||
// Add photo
|
||||
if (photo_.getType() == Photo::Type::Id)
|
||||
multipart.parts.push_back({"photo", photo_.getId()});
|
||||
else if (photo_.getType() == Photo::Type::Buffer)
|
||||
{
|
||||
const char* data = photo_.getBuffer().data();
|
||||
std::size_t size = photo_.getBuffer().size();
|
||||
const std::string filename = photo_.getBuffer().filename();
|
||||
multipart.parts.push_back({"photo", cpr::Buffer(data, data + size, filename)});
|
||||
}
|
||||
else if (photo_.getType() == Photo::Type::File)
|
||||
multipart.parts.push_back({"photo", cpr::File(photo_.getFile().getFilename())});
|
||||
else if (photo_.getType() == Photo::Type::Url)
|
||||
multipart.parts.push_back({"photo", photo_.getUrl().getUrl()});
|
||||
|
||||
// Add caption
|
||||
if (caption_)
|
||||
multipart.parts.push_back({"caption", *caption_});
|
||||
|
||||
// Add disable_notification
|
||||
if (disableNotification_)
|
||||
multipart.parts.push_back({"disable_notification", disableNotification_->value()});
|
||||
|
||||
// Add reply_to_message_id
|
||||
if (replyToMessageId_)
|
||||
multipart.parts.push_back({"reply_to_message_id", replyToMessageId_->value()});
|
||||
|
||||
auto r = cpr::Post(cpr::Url{telegramMainUrl_ + "/sendPhoto"}, multipart);
|
||||
auto& response = r.text;
|
||||
|
||||
if (debugMode)
|
||||
std::cout << "Response: " << response << std::endl;
|
||||
|
||||
rapidjson::Document doc;
|
||||
doc.Parse(response.c_str());
|
||||
|
||||
/// \todo Parse message
|
||||
checkResponse(doc);
|
||||
return *parseMessage(doc, "result", REQUIRED);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string telegramMainUrl_;
|
||||
ChatId chatId_;
|
||||
Photo photo_;
|
||||
boost::optional<Caption> caption_;
|
||||
boost::optional<DisableNotification> disableNotification_;
|
||||
boost::optional<ReplyTo> replyToMessageId_;
|
||||
};
|
||||
|
||||
SendPhotoRequest::SendPhotoRequest(const std::string& telegramMainUrl, const ChatId& chat, const Photo& photo)
|
||||
: impl_(std::make_unique<Impl>(telegramMainUrl, chat, photo))
|
||||
{
|
||||
}
|
||||
|
||||
SendPhotoRequest::~SendPhotoRequest()
|
||||
{
|
||||
}
|
||||
|
||||
void SendPhotoRequest::setCaption(const Caption& caption)
|
||||
{
|
||||
impl_->setCaption(caption);
|
||||
}
|
||||
|
||||
void SendPhotoRequest::setDisableNotification(const DisableNotification& disableNotification)
|
||||
{
|
||||
impl_->setDisableNotification(disableNotification);
|
||||
}
|
||||
|
||||
void SendPhotoRequest::setReplyToMessageId(const ReplyTo& replyToMessageId)
|
||||
{
|
||||
impl_->setReplyToMessageId(replyToMessageId);
|
||||
}
|
||||
|
||||
void SendPhotoRequest::setOption(const Caption& caption)
|
||||
{
|
||||
setCaption(caption);
|
||||
}
|
||||
|
||||
void SendPhotoRequest::setOption(const DisableNotification& disableNotification)
|
||||
{
|
||||
setDisableNotification(disableNotification);
|
||||
}
|
||||
|
||||
void SendPhotoRequest::setOption(const ReplyTo& replyToMessageId)
|
||||
{
|
||||
setReplyToMessageId(replyToMessageId);
|
||||
}
|
||||
|
||||
Message SendPhotoRequest::execute()
|
||||
{
|
||||
return impl_->execute();
|
||||
}
|
||||
|
|
@ -143,18 +143,59 @@ BOOST_AUTO_TEST_SUITE(TestBotApi)
|
|||
));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(SendPhoto)
|
||||
BOOST_AUTO_TEST_CASE(SendPhotoFile)
|
||||
{
|
||||
PRINT_TESTNAME;
|
||||
BOOST_REQUIRE(bot);
|
||||
BOOST_REQUIRE_NO_THROW(bot->sendPhoto(chat, photoFile, "Sample caption"));
|
||||
BOOST_REQUIRE_NO_THROW(bot->sendPhoto(chat,
|
||||
Photo{File{photoFile}}
|
||||
));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(SendPhotoFileWithCaption)
|
||||
{
|
||||
PRINT_TESTNAME;
|
||||
BOOST_REQUIRE(bot);
|
||||
BOOST_REQUIRE_NO_THROW(bot->sendPhoto(chat,
|
||||
Photo{File{photoFile}},
|
||||
Caption{"Photo with caption"}
|
||||
));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(SendPhotoInMemory)
|
||||
{
|
||||
PRINT_TESTNAME;
|
||||
BOOST_REQUIRE(bot);
|
||||
std::ifstream file(photoFile, std::ios::binary | std::ios::ate);
|
||||
std::size_t size = static_cast<std::size_t>(file.tellg());
|
||||
file.seekg(0, std::ios::beg);
|
||||
std::vector<char> buffer(size);
|
||||
BOOST_REQUIRE(file.read(buffer.data(), size));
|
||||
BOOST_REQUIRE_NO_THROW(bot->sendPhoto(chat,
|
||||
Photo{Buffer{buffer.data(), size, photoFile}},
|
||||
Caption{"Photo sent in-memory"}
|
||||
));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(SendPhotoUrl)
|
||||
{
|
||||
PRINT_TESTNAME;
|
||||
BOOST_REQUIRE(bot);
|
||||
BOOST_REQUIRE_NO_THROW(bot->sendPhotoUrl(chat, photoUrl, "Sample caption"));
|
||||
BOOST_REQUIRE_NO_THROW(bot->sendPhoto(chat,
|
||||
Photo{Url{photoUrl}},
|
||||
Caption{"Photo sent by URL"}
|
||||
));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(SendPhotoWithoutNotification)
|
||||
{
|
||||
PRINT_TESTNAME;
|
||||
BOOST_REQUIRE(bot);
|
||||
BOOST_REQUIRE_NO_THROW(bot->sendPhoto(chat,
|
||||
Photo{File{photoFile}},
|
||||
Caption{"Photo without notification"},
|
||||
DisableNotification()
|
||||
));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(GetUpdates)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue