Skip to content

Commit

Permalink
Added SendSticker and getStickerSet Api Methods
Browse files Browse the repository at this point in the history
  • Loading branch information
baderouaich committed Feb 24, 2024
1 parent 00df78b commit 636f518
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 7 deletions.
39 changes: 38 additions & 1 deletion include/tgbotxx/Api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ namespace tgbotxx {
struct LabeledPrice;
struct ShippingOption;
struct SentWebAppMessage;
struct ReplyParameters;
struct StickerSet;

/// @brief Api Methods https://core.telegram.org/bots/api#available-methods
/// @note All methods in the Bot API are case-insensitive.
Expand All @@ -63,6 +65,7 @@ namespace tgbotxx {
cpr::Timeout m_downloadFilesTimeout = DEFAULT_DOWNLOAD_FILES_TIMEOUT; /// Api files download timeout

friend class Bot;

public:
/// @brief Constructs Api object.
/// @param token Bot Token from FatherBot.
Expand Down Expand Up @@ -232,7 +235,7 @@ namespace tgbotxx {
/// @note For sending voice messages, use the sendVoice method instead.
/// @ref https://core.telegram.org/bots/api#sendaudio
Ptr<Message> sendAudio(const std::variant<std::int64_t, std::string>& chatId,
std::variant<cpr::File, std::string> audio,
const std::variant<cpr::File, std::string>& audio,
std::int32_t messageThreadId = 0,
const std::string& caption = "",
const std::string& parseMode = "",
Expand Down Expand Up @@ -1748,6 +1751,40 @@ namespace tgbotxx {
/// @ref https://core.telegram.org/bots/api#deletemessage
bool deleteMessage(const std::variant<std::int64_t, std::string>& chatId, std::int32_t messageId) const;

public: /// Stickers
/// @brief Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned.
/// @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername)
/// @param sticker Sticker to send.
/// - Pass a file_id std::string to send a file that exists on the Telegram servers (recommended),
/// - Pass an HTTP URL as an std::string for Telegram to get a .WEBP sticker from the Internet, or
/// - Pass a cpr::File to upload a new .WEBP or .TGS sticker
/// @param messageThreadId Optional. Unique identifier for the target message thread (topic) of the forum; for forum supergroups only
/// @param emoji Optional. Emoji associated with the sticker; only for just uploaded stickers
/// @param disableNotification Optional. Sends the message silently. Users will receive a notification with no sound.
/// @param protectContent Optional. Protects the contents of the sent message from forwarding and saving
/// @param replyParameters Optional. Description of the message to reply to
/// @param replyMarkup Optional. Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
/// One of InlineKeyboardMarkup or ReplyKeyboardMarkup or ReplyKeyboardRemove or ForceReply.
/// @returns sent Message object on success.
/// @throws Exception on failure
/// @ref https://core.telegram.org/bots/api#sendsticker
Ptr<Message> sendSticker(const std::variant<std::int64_t, std::string>& chatId,
const std::variant<cpr::File, std::string>& sticker,
std::int32_t messageThreadId = 0,
const std::string& emoji = "",
bool disableNotification = false,
bool protectContent = false,
const Ptr<ReplyParameters>& replyParameters = nullptr,
const Ptr<IReplyMarkup>& replyMarkup = nullptr) const;

/// @brief Use this method to get a sticker set. On success, a StickerSet object is returned.
/// @param name Name of the sticker set
/// @returns StickerSet object is returned on success.
/// @throws Exception on failure
/// @ref https://core.telegram.org/bots/api#getstickerset
Ptr<StickerSet> getStickerSet(const std::string& name) const;


public: /// Inline mode methods. Methods and objects used in the inline mode are described in the Inline mode section. https://core.telegram.org/bots/api#inline-mode
/// @brief Use this method to send answers to an inline query.
/// No more than 50 results per query are allowed.
Expand Down
72 changes: 67 additions & 5 deletions src/Api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <tgbotxx/objects/BotShortDescription.hpp>
#include <tgbotxx/objects/CallbackGame.hpp>
#include <tgbotxx/objects/CallbackQuery.hpp>
#include <tgbotxx/objects/StickerSet.hpp>
#include <tgbotxx/objects/Chat.hpp>
#include <tgbotxx/objects/ChatAdministratorRights.hpp>
#include <tgbotxx/objects/ChatInviteLink.hpp>
Expand Down Expand Up @@ -70,6 +71,7 @@
#include <tgbotxx/objects/ProximityAlertTriggered.hpp>
#include <tgbotxx/objects/ReplyKeyboardMarkup.hpp>
#include <tgbotxx/objects/ReplyKeyboardRemove.hpp>
#include <tgbotxx/objects/ReplyParameters.hpp>
#include <tgbotxx/objects/SentWebAppMessage.hpp>
#include <tgbotxx/objects/ShippingAddress.hpp>
#include <tgbotxx/objects/ShippingOption.hpp>
Expand Down Expand Up @@ -309,7 +311,7 @@ Ptr<Message> Api::sendPhoto(const std::variant<std::int64_t, std::string>& chatI
}

Ptr<Message> Api::sendAudio(const std::variant<std::int64_t, std::string>& chatId,
std::variant<cpr::File, std::string> audio,
const std::variant<cpr::File, std::string>& audio,
std::int32_t messageThreadId,
const std::string& caption,
const std::string& parseMode,
Expand Down Expand Up @@ -733,10 +735,9 @@ std::vector<Ptr<Message>> Api::sendMediaGroup(const std::variant<std::int64_t, s
throw Exception("Api::sendMediaGroup(): media must include 2-10 items. See https://core.telegram.org/bots/api#sendmediagroup");
nl::json mediaJson = nl::json::array();
// Handle local media files if available, see https://core.telegram.org/bots/api#inputmediaphoto
for (const Ptr<InputMedia>& m: media)
{
for (const Ptr<InputMedia>& m: media) {
nl::json mJson = m->toJson();
switch(m->media.index()) {
switch (m->media.index()) {
case 0: // cpr::File (Local File)
{
const cpr::File& file = std::get<cpr::File>(m->media);
Expand Down Expand Up @@ -2057,7 +2058,7 @@ bool Api::answerInlineQuery(const std::string& inlineQueryId,
data.parts.emplace_back("cache_time", cacheTime);
if (isPersonal)
data.parts.emplace_back("is_personal", isPersonal);
if(not nextOffset.empty())
if (not nextOffset.empty())
data.parts.emplace_back("next_offset", nextOffset);
if (button)
data.parts.emplace_back("button", button->toJson().dump());
Expand All @@ -2077,6 +2078,67 @@ Ptr<SentWebAppMessage> Api::answerWebAppQuery(const std::string& webAppQueryId,
}


/////////////////////////////////////////////////////////////////////////////////////////////////

Ptr<Message> Api::sendSticker(const std::variant<std::int64_t, std::string>& chatId,
const std::variant<cpr::File, std::string>& sticker,
std::int32_t messageThreadId,
const std::string& emoji,
bool disableNotification,
bool protectContent,
const Ptr<tgbotxx::ReplyParameters>& replyParameters,
const Ptr<tgbotxx::IReplyMarkup>& replyMarkup) const {
cpr::Multipart data{};
data.parts.reserve(8);
switch (chatId.index()) {
case 0: // std::int64_t
if (std::int64_t chatIdInt = std::get<std::int64_t>(chatId); chatIdInt != 0) {
data.parts.emplace_back("chat_id", std::to_string(chatIdInt));
}
break;
case 1: // std::string
if (std::string chatIdStr = std::get<std::string>(chatId); not chatIdStr.empty()) {
data.parts.emplace_back("chat_id", chatIdStr);
}
break;
default:
break;
}
if (sticker.index() == 0) /* cpr::File */ {
const cpr::File& file = std::get<cpr::File>(sticker);
data.parts.emplace_back("sticker", cpr::Files{file});
} else /* std::string (fileId or Url) */ {
const std::string& fileIdOrUrl = std::get<std::string>(sticker);
data.parts.emplace_back("sticker", fileIdOrUrl);
}
if (messageThreadId)
data.parts.emplace_back("message_thread_id", messageThreadId);
if (not emoji.empty())
data.parts.emplace_back("emoji", emoji);
if (disableNotification)
data.parts.emplace_back("disable_notification", disableNotification);
if (protectContent)
data.parts.emplace_back("protect_content", protectContent);
if (replyParameters)
data.parts.emplace_back("reply_parameters", replyParameters->toJson().dump());
if (replyMarkup)
data.parts.emplace_back("reply_markup", replyMarkup->toJson().dump());

nl::json sentMessageObj = sendRequest("sendSticker", data);
Ptr<Message> message(new Message(sentMessageObj));
return message;
}


Ptr<StickerSet> Api::getStickerSet(const std::string& name) const {
cpr::Multipart data{};
data.parts.reserve(1);
data.parts.emplace_back("name", name);

nl::json stickerSetObj = sendRequest("getStickerSet", data);
Ptr<StickerSet> stickerSet(new StickerSet(stickerSetObj));
return stickerSet;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
void Api::setUrl(const std::string& url) noexcept {
m_apiUrl = url;
Expand Down
7 changes: 6 additions & 1 deletion tests/manual_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,13 @@ class MyBot : public Bot {
Ptr<BotCommand> createInvoiceLink(new BotCommand());
createInvoiceLink->command = "/create_invoice_link";
createInvoiceLink->description = "You will receive a test invoice link";
Ptr<BotCommand> sendSticker(new BotCommand());
sendSticker->command = "/send_sticker";
sendSticker->description = "You will receive a sticker";
getApi()->setMyCommands({greet, stop, photo, inlineButtons, replyKeyboardButtons, audio, document, animation, voice, mediaGroup,
location, userProfilePhotos, ban, poll, quiz, webhookInfo, botName,
menuButtonWebApp, menuButtonDefault, showAdministratorRights, editMessageText,
deleteMessage, sendInvoice, createInvoiceLink}); // The above commands will be shown in the bot chat menu (bottom left)
deleteMessage, sendInvoice, createInvoiceLink, sendSticker}); // The above commands will be shown in the bot chat menu (bottom left)

std::cout << __func__ << ": " << api()->getMyName()->name << " bot started!" << std::endl;
}
Expand Down Expand Up @@ -366,6 +369,8 @@ class MyBot : public Bot {
std::string link = api()->createInvoiceLink("Product name", "Product description", "payload", providerToken, "USD", prices);
// Send link to user
api()->sendMessage(message->chat->id, link);
} else if (message->text == "/send_sticker") {
api()->sendSticker(message->chat->id, "https://t.ly/uQ6Zx");
}
}

Expand Down

0 comments on commit 636f518

Please sign in to comment.