mirror of
https://github.com/UltraCoderRU/telebotxx.git
synced 2026-01-28 04:05:13 +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 "Message.hpp"
|
||||||
#include "Update.hpp"
|
#include "Update.hpp"
|
||||||
#include "SendMessageRequest.hpp"
|
#include "SendMessageRequest.hpp"
|
||||||
|
#include "SendPhotoRequest.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
@ -57,18 +58,23 @@ namespace telebotxx
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Send image
|
/// \brief Send image
|
||||||
/// \param [in] chat chat identifier
|
/// \param [in] chatId chat identifier
|
||||||
/// \param [in] filename image location
|
/// \param [in] photo photo
|
||||||
/// \param [in] caption optional photo caption
|
|
||||||
/// \return Message object, recieved from the server
|
/// \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
|
/// \brief Send image
|
||||||
/// \param [in] chat chat identifier
|
/// \param [in] chatId chat identifier
|
||||||
/// \param [in] url image URL
|
/// \param [in] photo photo
|
||||||
/// \param [in] caption optional photo caption
|
/// \param [in] args parameters
|
||||||
/// \return Message object, recieved from the server
|
/// \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
|
/// \brief Get updates using long polling
|
||||||
/// \param offset identifier of the first update to be returned
|
/// \param offset identifier of the first update to be returned
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define TELEBOTXX_REQUEST_OPTIONS_HPP
|
#define TELEBOTXX_REQUEST_OPTIONS_HPP
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace telebotxx
|
namespace telebotxx
|
||||||
{
|
{
|
||||||
|
|
@ -64,6 +65,20 @@ namespace telebotxx
|
||||||
int id_;
|
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
|
class File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -86,20 +101,27 @@ namespace telebotxx
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Photo(int id);
|
explicit Photo(int id);
|
||||||
|
explicit Photo(const Buffer&);
|
||||||
explicit Photo(const File&);
|
explicit Photo(const File&);
|
||||||
explicit Photo(const Url&);
|
explicit Photo(const Url&);
|
||||||
Photo(const Photo&);
|
Photo(const Photo&);
|
||||||
Photo(Photo&&);
|
Photo(Photo&&);
|
||||||
~Photo();
|
~Photo();
|
||||||
|
|
||||||
enum class Type { File, Url, Id };
|
enum class Type { Id, Buffer, File, Url};
|
||||||
Type getType() const;
|
Type getType() const;
|
||||||
|
|
||||||
|
int getId() const;
|
||||||
|
const Buffer& getBuffer() const;
|
||||||
|
const File& getFile() const;
|
||||||
|
const Url& getUrl() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type type_;
|
Type type_;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
int id_;
|
int id_;
|
||||||
|
Buffer buffer_;
|
||||||
File file_;
|
File file_;
|
||||||
Url url_;
|
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();
|
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);
|
SendPhotoRequest request(getTelegramMainUrl(), std::forward<ChatId>(chatId), std::forward<Photo>(photo));
|
||||||
}
|
return request.execute();
|
||||||
|
|
||||||
Message BotApi::sendPhotoUrl(const std::string& chat, const std::string& url, const std::string& caption)
|
|
||||||
{
|
|
||||||
return impl_->sendPhotoUrl(chat, url, caption);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Updates BotApi::getUpdates(int offset, unsigned short limit, unsigned int timeout)
|
Updates BotApi::getUpdates(int offset, unsigned short limit, unsigned int timeout)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ set(SOURCE_FILES Attachment.cpp
|
||||||
User.cpp
|
User.cpp
|
||||||
RequestOptions.cpp
|
RequestOptions.cpp
|
||||||
SendMessageRequest.cpp
|
SendMessageRequest.cpp
|
||||||
|
SendPhotoRequest.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(telebotxx SHARED ${SOURCE_FILES})
|
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)
|
File::File(const std::string& filename)
|
||||||
: filename_(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)
|
Photo::Photo(const File& file)
|
||||||
: type_(Type::File), file_(file)
|
: type_(Type::File), file_(file)
|
||||||
{
|
{
|
||||||
|
|
@ -139,12 +171,38 @@ Photo::Photo(const Photo& other)
|
||||||
{
|
{
|
||||||
if (type_ == Type::Id)
|
if (type_ == Type::Id)
|
||||||
id_ = other.id_;
|
id_ = other.id_;
|
||||||
|
else if (type_ == Type::Buffer)
|
||||||
|
new(&buffer_) Buffer(other.buffer_);
|
||||||
else if (type_ == Type::File)
|
else if (type_ == Type::File)
|
||||||
new(&file_) File(other.file_);
|
new(&file_) File(other.file_);
|
||||||
else
|
else
|
||||||
new(&url_) Url(other.url_);
|
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()
|
Photo::~Photo()
|
||||||
{
|
{
|
||||||
if (type_ == Type::File)
|
if (type_ == Type::File)
|
||||||
|
|
@ -156,4 +214,24 @@ Photo::~Photo()
|
||||||
Photo::Type Photo::getType() const
|
Photo::Type Photo::getType() const
|
||||||
{
|
{
|
||||||
return type_;
|
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;
|
PRINT_TESTNAME;
|
||||||
BOOST_REQUIRE(bot);
|
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)
|
BOOST_AUTO_TEST_CASE(SendPhotoUrl)
|
||||||
{
|
{
|
||||||
PRINT_TESTNAME;
|
PRINT_TESTNAME;
|
||||||
BOOST_REQUIRE(bot);
|
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)
|
BOOST_AUTO_TEST_CASE(GetUpdates)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue