4
1
mirror of https://github.com/QuasarApp/qTbot.git synced 2025-05-11 20:59:37 +00:00

adde first implementation for the keyboard support

This commit is contained in:
Andrei Yankovich 2023-10-07 23:03:48 +02:00
parent f984355a33
commit 09333936f2
6 changed files with 241 additions and 14 deletions

@ -6,17 +6,21 @@
//#
#include "telegramsendmsg.h"
#include <QJsonDocument>
#include <QJsonObject>
namespace qTbot {
TelegramSendMsg::TelegramSendMsg(const QVariant &chatId,
const QString &text,
const QMap<QString, QJsonObject> &extraObjects,
unsigned long long replyToMessageId,
bool markdown,
bool disableWebPagePreview):
bool disableWebPagePreview)
:
TelegramSingleRquest("sendMessage")
{
QMap<QString, QVariant> args {{"chat_id", chatId}, {"text", text}};
if (replyToMessageId) {
@ -31,6 +35,10 @@ TelegramSendMsg::TelegramSendMsg(const QVariant &chatId,
args["disable_web_page_preview"] = disableWebPagePreview;
}
for (auto it = extraObjects.begin(); it != extraObjects.end(); it = std::next(it)) {
args[it.key()] = QJsonDocument(it.value()).toJson();
}
setArgs(args);
}
}

@ -19,9 +19,11 @@ class QTBOT_EXPORT TelegramSendMsg: public TelegramSingleRquest
public:
TelegramSendMsg(const QVariant& chatId,
const QString& text,
const QMap<QString, QJsonObject>& extraObjects = {},
unsigned long long replyToMessageId = 0,
bool markdown = true,
bool disableWebPagePreview = false);
bool disableWebPagePreview = false
);
};
}
#endif // TELEGRAMSENDMSG_H

@ -38,7 +38,7 @@ void IBot::incomeNewUpdate(const QSharedPointer<iUpdate> &message) {
_processed.insert(id);
_notProcessedUpdates[id] = message;
emit sigReceiveUpdate(message);
handleIncomeNewUpdate(message);
}
}
@ -84,6 +84,10 @@ QString IBot::defaultFileStorageLocation() const {
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
}
void IBot::handleIncomeNewUpdate(const QSharedPointer<iUpdate> & message) {
emit sigReceiveUpdate(message);
}
void IBot::doRemoveFinishedRequests() {
for (auto address: qAsConst(_toRemove)) {
_replayStorage.remove(address);

@ -184,6 +184,12 @@ protected:
* @return default file storage.
*/
virtual QString defaultFileStorageLocation() const;
/**
* @brief handleIncomeNewUpdate This method just emit the sigReceiveUpdate signal.
* @note you may override this method for filter the sigReceiveUpdate signal or for handling new updates.
*/
virtual void handleIncomeNewUpdate(const QSharedPointer<iUpdate>& );
signals:
/**
* @brief sigReceiveUpdate emit when but receive any updates from users.

@ -20,6 +20,8 @@
#include <QNetworkReply>
#include <QSharedPointer>
#include <QDebug>
#include <QJsonArray>
#include <QJsonObject>
#include <qTbot/messages/telegramfile.h>
#include <qTbot/messages/telegramfile.h>
@ -28,6 +30,7 @@
namespace qTbot {
ITelegramBot::ITelegramBot() {
}
ITelegramBot::~ITelegramBot() {
@ -60,6 +63,7 @@ bool ITelegramBot::sendMessage(const QVariant &chatId, const QString &text) {
bool ITelegramBot::sendSpecificMessage(const QVariant & chatId,
const QString &text,
const QMap<QString, QJsonObject> &extraObjects,
unsigned long long replyToMessageId,
bool markdown,
bool disableWebPagePreview) {
@ -73,6 +77,90 @@ bool ITelegramBot::sendSpecificMessage(const QVariant & chatId,
auto msg = QSharedPointer<TelegramSendMsg>::create(chatId,
text,
extraObjects,
replyToMessageId,
markdown,
disableWebPagePreview);
return bool(sendRequest(msg));
}
bool ITelegramBot::sendSpecificMessage(const QVariant &chatId,
const QString &text,
const QList<QString> &keyboard,
bool onTimeKeyboard,
bool autoResizeKeyboard,
unsigned long long replyToMessageId,
bool markdown,
bool disableWebPagePreview) {
if (!chatId.isValid() || chatId.isNull())
return false;
if (text.isEmpty()) {
return false;
}
QMap<QString, QJsonObject> extraObjects;
QJsonObject keyboardJson;
QJsonArray keyboardArray;
for (auto it = keyboard.begin(); it != keyboard.end(); it = std::next(it)) {
auto&& callBackKey = QString("callback_data_%0").arg(rand());
keyboardArray.push_back(QJsonObject{ {"text", *it} });
}
keyboardJson["keyboard"] = keyboardArray;
keyboardJson["resize_keyboard"] = autoResizeKeyboard;
keyboardJson["one_time_keyboard"] = onTimeKeyboard;
extraObjects["reply_markup"] = keyboardJson;
auto msg = QSharedPointer<TelegramSendMsg>::create(chatId,
text,
extraObjects,
replyToMessageId,
markdown,
disableWebPagePreview);
return bool(sendRequest(msg));
}
bool ITelegramBot::sendSpecificMessage(const QVariant &chatId,
const QString &text,
const QMap<QString, std::function<void()> > &keyboard,
bool onTimeKeyboard,
bool autoResizeKeyboard,
unsigned long long replyToMessageId,
bool markdown,
bool disableWebPagePreview) {
if (!chatId.isValid() || chatId.isNull())
return false;
if (text.isEmpty()) {
return false;
}
QMap<QString, QJsonObject> extraObjects;
QJsonObject keyboardJson;
QJsonArray keyboardArray;
for (auto it = keyboard.begin(); it != keyboard.end(); it = std::next(it)) {
auto&& callBackKey = QString("callback_data_%0").arg(rand());
keyboardArray.push_back(QJsonObject{ {"text", it.key()}, {"callback_data", callBackKey } });
_handleButtons[callBackKey] = {it.value(), onTimeKeyboard};
}
keyboardJson["inline_keyboard"] = keyboardArray;
keyboardJson["resize_keyboard"] = autoResizeKeyboard;
keyboardJson["one_time_keyboard"] = onTimeKeyboard;
extraObjects["reply_markup"] = keyboardJson;
auto msg = QSharedPointer<TelegramSendMsg>::create(chatId,
text,
extraObjects,
replyToMessageId,
markdown,
disableWebPagePreview);
@ -180,6 +268,24 @@ void ITelegramBot::onRequestError(const QSharedPointer<TelegramUpdateAnswer> &an
arg(ansverWithError->errorDescription());
}
void ITelegramBot::handleIncomeNewUpdate(const QSharedPointer<iUpdate> & update) {
IBot::handleIncomeNewUpdate(update);
if (auto&& tupdate = update.dynamicCast<TelegramUpdate>()) {
if (auto&& msg = tupdate->message()) {
auto &&handleButtonKey = msg->text();
auto [cb, isOneTimeKeyboard] = _handleButtons.value(handleButtonKey);
cb();
if (isOneTimeKeyboard) {
_handleButtons.remove(handleButtonKey);
}
}
}
}
void ITelegramBot::handleLogin() {
if (_loginReplay) {

@ -37,16 +37,17 @@ public:
bool sendMessage(const QVariant &chatId, const QString& text) override;
/**
* @brief Sends a message to a chat or channel.
* @brief Sends a message to a chat or channel with optional additional objects.
*
* The `sendMessage` method is used to send a message to a chat. This method allows
* The `sendSpecificMessage` method is used to send a message to a chat. This method allows
* sending text messages to chats and channels. You can also specify additional
* parameters such as text formatting, a reply to a specific message, and disabling
* web page preview.
* parameters such as text formatting, a reply to a specific message, disabling
* web page preview, and including extra JSON objects in the message.
*
* @param chatId The identifier of the chat or channel to which the message will be sent.
* It can be a string, number, or another valid data type containing the chat identifier.
* @param text The text of the message to be sent.
* @param extraObjects A map containing additional JSON objects to include in the message.
* @param replyToMessageId The identifier of the message to which you want to reply. If you want to send
* a regular message without a reply, leave this field as 0.
* @param markdown A flag indicating whether the message text should be formatted using Markdown.
@ -60,21 +61,119 @@ public:
* Usage examples:
* @code
* // Send a plain text message
* bool result = sendMessage(chatId, "Hello, world!");
* bool result = sendSpecificMessage(chatId, "Hello, world!");
*
* // Send a formatted text message as a reply to another message
* bool result = sendMessage(chatId, "This is a reply to your message.", messageId);
* // Send a formatted text message as a reply to another message with additional JSON objects
* QMap<QString, QJsonObject> additionalObjects = {
* {"key1", {"value1"}},
* {"key2", {"value2"}}
* };
* bool result = sendSpecificMessage(chatId, "This is a reply with additional objects.", additionalObjects, messageId);
*
* // Send a message with disabled web page preview
* bool result = sendMessage(chatId, "Check)", 0, true, true);
* bool result = sendSpecificMessage(chatId, "Check)", {}, 0, true, true);
* @endcode
*/
bool sendSpecificMessage(const QVariant &chatId,
const QString& text,
const QMap<QString, QJsonObject> &extraObjects = {},
unsigned long long replyToMessageId = 0,
bool markdown = true,
bool disableWebPagePreview = false);
/**
* @brief Sends a message to a chat or channel with an optional custom keyboard **inline keyboard**.
*
* The `sendSpecificMessage` method is used to send a message to a chat. This method allows
* sending text messages to chats and channels. You can also specify additional
* parameters such as text formatting, a reply to a specific message, disabling
* web page preview, and providing a custom keyboard for interaction.
*
* @param chatId The identifier of the chat or channel to which the message will be sent.
* It can be a string, number, or another valid data type containing the chat identifier.
* @param text The text of the message to be sent.
* @param keyboard A map containing buttons and corresponding callback functions for a custom keyboard.
* @param replyToMessageId The identifier of the message to which you want to reply. If you want to send
* a regular message without a reply, leave this field as 0.
* @param markdown A flag indicating whether the message text should be formatted using Markdown.
* If `true`, the text will be formatted using Markdown syntax. If `false`, the text will be
* sent as plain text.
* @param disableWebPagePreview A flag indicating whether to disable web page preview in the message.
* If `true`, web page preview will be disabled.
*
* @return `true` if the message was successfully sent, and `false` otherwise.
*
* Usage examples:
* @code
* // Send a plain text message
* bool result = sendSpecificMessage(chatId, "Hello, world!");
*
* // Send a formatted text message as a reply to another message with a custom keyboard
* QMap<QString, std::function<void>> customKeyboard = {
* {"Button 1", [](){ Callback function for Button 1 }},
* {"Button 2", [](){ Callback function for Button 2 }}
* };
* bool result = sendSpecificMessage(chatId, "This is a reply with a custom keyboard.", customKeyboard, true, messageId);
*
* // Send a message with disabled web page preview
* bool result = sendSpecificMessage(chatId, "Check)", {}, false, 0, true, true);
* @endcode
*/
bool sendSpecificMessage(const QVariant &chatId,
const QString& text,
const QMap<QString, std::function<void()>> &keyboard,
bool onTimeKeyboard = false,
bool autoResizeKeyboard = false,
unsigned long long replyToMessageId = 0,
bool markdown = true,
bool disableWebPagePreview = false);
/**
* @brief sendSpecificMessage sends a specific message with a keyboard to a chat.
*
* This method sends a specific message with a keyboard to a chat. It allows
* you to customize various aspects of the message, such as the text, keyboard,
* and other options.
*
* @param chatId The identifier of the chat to which the message will be sent.
* @param text The text of the message to be sent.
* @param keyboard A list of text buttons for the keyboard placed below the message.
* @param onTimeKeyboard A flag indicating whether the keyboard should be hidden after
* selecting one of the buttons (one-time keyboard).
* @param autoResizeKeyboard A flag indicating whether the keyboard should automatically
* adjust its size based on the number of buttons.
* @param replyToMessageId The identifier of the message to which this message is a reply
* (if applicable).
* @param markdown A flag indicating whether Markdown formatting is supported in the message text.
* @param disableWebPagePreview A flag indicating whether to disable web page preview in the message.
*
* @return Returns true if the message was successfully sent, and false in case of an error.
*
* @example
* @code
* bool result = sendSpecificMessage(chatId, "Hello, how are you?", {"Button 1", "Button 2"}, true, true, 0, true, false);
* if (result) {
* qDebug() << "Message sent successfully.";
* } else {
* qDebug() << "Error sending the message.";
* }
* @endcode
*
* @note If the onTimeKeyboard parameter is set to true, the keyboard will be hidden after selecting
* one of the buttons, and the user won't be able to use it again.
* @note If the autoResizeKeyboard parameter is set to true, the keyboard will automatically adjust
* its size based on the number of buttons.
* @note The markdown and disableWebPagePreview parameters allow you to configure text formatting
* and web page preview options in the message.
*/
bool sendSpecificMessage(const QVariant &chatId,
const QString& text,
const QList<QString> &keyboard,
bool onTimeKeyboard = false,
bool autoResizeKeyboard = false,
unsigned long long replyToMessageId = 0,
bool markdown = true,
bool disableWebPagePreview = false);
[[nodiscard("do not forget to save shared pointer of file handler, because it's will not save inner bot object.")]]
QSharedPointer<iFile> getFile(const QString& fileId, iFile::Type fileType = iFile::Type::Ram) override;
@ -178,6 +277,9 @@ protected:
* @param ansverWithError - This is ansver object with error descriptions. and codes errors.
*/
virtual void onRequestError(const QSharedPointer<TelegramUpdateAnswer>& ansverWithError) const;
void handleIncomeNewUpdate(const QSharedPointer<iUpdate> &) override;
private slots:
void handleLogin();
void handleLoginErr(QNetworkReply::NetworkError err);
@ -190,11 +292,10 @@ private:
unsigned long long _id = 0;
QString _username;
QSharedPointer<QNetworkReply> _loginReplay;
QMap<QString, QPair<std::function<void()>, bool>> _handleButtons;
QHash<QString, QSharedPointer<TelegramFile>> _filesMetaInfo;
};
}
#endif // ITELEGRAMBOT_H