diff --git a/src/qTbot/src/private/requests/telegramsinglerquest.cpp b/src/qTbot/src/private/requests/telegramsinglerquest.cpp index c6af59b..c7cb1b7 100644 --- a/src/qTbot/src/private/requests/telegramsinglerquest.cpp +++ b/src/qTbot/src/private/requests/telegramsinglerquest.cpp @@ -16,58 +16,15 @@ namespace qTbot { TelegramSingleRquest::TelegramSingleRquest(const QString& request, const QMap<QString, QVariant>& args) { - _request = std::move(request); - _args = std::move(args); -} + setRequest(request); + setArgs(args);} TelegramSingleRquest::TelegramSingleRquest(const QString &request) { - _request = std::move(request); + setRequest(request); } - -QString TelegramSingleRquest::makeUpload() const { - - if (_args.isEmpty()) { - return "/" + _request; - } - - QByteArray args; - - auto it = _args.constBegin(); - while (it != _args.constEnd()) { - if (args.isEmpty()) { - args.append(QString("%0=%1").arg(it.key(), it->toString()).toUtf8()); - } else { - args.append(QString("&%0=%1").arg(it.key(), it->toString()).toUtf8()); - } - ++it; - } - - return "/" + _request + "?" + args; - -} - +\ QString TelegramSingleRquest::baseAddress() const { return "https://api.telegram.org"; } -const QMap<QString, QVariant>& TelegramSingleRquest::args() const { - return _args; -} - -void TelegramSingleRquest::addArg(const QString &key, const QVariant &val) { - _args[key] = val; -} - -void TelegramSingleRquest::setArgs(const QMap<QString, QVariant> &newArgs) { - _args = newArgs; -} - -const QString& TelegramSingleRquest::request() const { - return _request; -} - -void TelegramSingleRquest::setRequest(const QString &newRequest) { - _request = newRequest; -} - } diff --git a/src/qTbot/src/private/requests/telegramsinglerquest.h b/src/qTbot/src/private/requests/telegramsinglerquest.h index 0685e5c..c04cae4 100644 --- a/src/qTbot/src/private/requests/telegramsinglerquest.h +++ b/src/qTbot/src/private/requests/telegramsinglerquest.h @@ -50,45 +50,8 @@ public: */ TelegramSingleRquest(const QString& request); - QString makeUpload() const override final; QString baseAddress() const override; -protected: - - /** - * @brief request return current requests commnad. - * @return current requests commnad. - */ - const QString& request() const; - - /** - * @brief setRequest sets custom requests commnad - * @param newRequest new custom commnad of the request. - */ - void setRequest(const QString &newRequest); - - /** - * @brief args This method returns a current list of arguments - * @return current list of arguments - */ - const QMap<QString, QVariant> &args() const; - - /** - * @brief addArg This method push new arg, to arguments list - * @param key This is new argument key - * @param val this is new argument value. - */ - void addArg(const QString& key, const QVariant& val); - - /** - * @brief setArgs For the some requests list of arguments posible to build only after constructor. - * @param newArgs This is new list of arguments. - */ - void setArgs(const QMap<QString, QVariant> &newArgs); - -private: - QString _request; - QMap<QString, QVariant> _args; }; } diff --git a/src/qTbot/src/public/qTbot/ibot.cpp b/src/qTbot/src/public/qTbot/ibot.cpp index 057e930..78b142e 100644 --- a/src/qTbot/src/public/qTbot/ibot.cpp +++ b/src/qTbot/src/public/qTbot/ibot.cpp @@ -44,7 +44,8 @@ void IBot::incomeNewUpdate(const QSharedPointer<iUpdate> &message) { } } -QSharedPointer<QNetworkReply> IBot::sendRequest(const QSharedPointer<iRequest> &rquest) { +QSharedPointer<QNetworkReply> +IBot::sendRequest(const QSharedPointer<iRequest> &rquest, RequestMethod method) { if (!rquest) return nullptr; @@ -56,9 +57,25 @@ QSharedPointer<QNetworkReply> IBot::sendRequest(const QSharedPointer<iRequest> & qDebug() << url; #endif - auto&& networkReplay = QSharedPointer<QNetworkReply>( - _manager->get(QNetworkRequest(url))); + QSharedPointer<QNetworkReply> networkReplay; + switch (method) { + case Get: + networkReplay.reset(_manager->get(QNetworkRequest(url))); + break; + case Post: +// req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); +// reply = m_nam.post(req, params.toByteArray()); + +// break; + case Upload: + QByteArray boundary = params.toMultipartBoundary(); + req.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary=" + boundary); + QByteArray requestData = params.generateMultipartFormData(boundary); + req.setHeader(QNetworkRequest::ContentLengthHeader, requestData.length()); + reply = m_nam.post(req, requestData); + break; + } size_t address = reinterpret_cast<size_t>(networkReplay.get()); _replayStorage[address] = networkReplay; diff --git a/src/qTbot/src/public/qTbot/ibot.h b/src/qTbot/src/public/qTbot/ibot.h index ffb005a..deb0f62 100644 --- a/src/qTbot/src/public/qTbot/ibot.h +++ b/src/qTbot/src/public/qTbot/ibot.h @@ -168,10 +168,11 @@ protected: /** * @brief sendRequest This method sent custom requests to the server. * @param rquest This is message that will be sent to server. + * @param method This is method how will data sent * @return shared pointer to the request replay. * @note The raplay will be removed from local storage only after error or finishing, If you want to save replay just make local copy of the shared pointer. */ - QSharedPointer<QNetworkReply> sendRequest(const QSharedPointer<iRequest>& rquest); + QSharedPointer<QNetworkReply> sendRequest(const QSharedPointer<iRequest>& rquest, RequestMethod method = RequestMethod::Get); /** * @brief setToken This is setter of the IBot::token value. diff --git a/src/qTbot/src/public/qTbot/irequest.cpp b/src/qTbot/src/public/qTbot/irequest.cpp index 1bc7549..c5e5884 100644 --- a/src/qTbot/src/public/qTbot/irequest.cpp +++ b/src/qTbot/src/public/qTbot/irequest.cpp @@ -6,6 +6,9 @@ //# #include "irequest.h" +#include "qvariant.h" + +#include <QBuffer> namespace qTbot { @@ -14,4 +17,82 @@ iRequest::iRequest() } +QString iRequest::makeUpload() const { + + if (_args.isEmpty() || method() != Get) { + return "/" + _request; + } + + return "/" + _request + "?" + argsToUrl(); + +} + +const QMap<QString, QVariant>& iRequest::args() const { + return _args; +} + +void iRequest::addArg(const QString &key, const QVariant &val) { + _args[key] = val; +} + +void iRequest::setArgs(const QMap<QString, QVariant> &newArgs) { + _args = newArgs; +} + +QString iRequest::argsToUrl() const { + QString args; + + auto it = _args.constBegin(); + while (it != _args.constEnd()) { + if (args.isEmpty()) { + args.append(QString("%0=%1").arg(it.key(), it->toString()).toUtf8()); + } else { + args.append(QString("&%0=%1").arg(it.key(), it->toString()).toUtf8()); + } + ++it; + } + + return args; +} + +QHttpMultiPart iRequest::argsToMultipartFormData() const { + QHttpMultiPart multiPart(QHttpMultiPart::FormDataType); + + auto it = _args.constBegin(); + while (it != _args.constEnd()) { + QHttpPart part; + auto && value = it.value(); + if (value.typeId() == QMetaType::QByteArray) { + QByteArray && array = value.toByteArray(); + + if (array.left(5) == "file:") { + const auto metaData = array.split(':'); + if (metaData.size() == 3) { + const auto fileName = metaData[1]; + const QByteArray fileData = metaData[2]; + part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"document\"; filename=\"" + fileName + "\"")); + part.setBody(fileData); + } else { + qWarning() << "the file arguments must be like file:fileName:Data"; + } + + } else { + part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + it.key() + "\"")); + part.setBody(it.value().toByteArray()); + } + } + multiPart.append(part); + + ++it; + } + multiPart.append(chatIdPart); +} + +const QString& iRequest::request() const { + return _request; +} + +void iRequest::setRequest(const QString &newRequest) { + _request = newRequest; +} } diff --git a/src/qTbot/src/public/qTbot/irequest.h b/src/qTbot/src/public/qTbot/irequest.h index f0fbbc6..c4c694a 100644 --- a/src/qTbot/src/public/qTbot/irequest.h +++ b/src/qTbot/src/public/qTbot/irequest.h @@ -11,6 +11,11 @@ #include "qTbot/global.h" +#include <QByteArray> +#include <QMap> +#include <QString> +#include <QHttpMultiPart> + namespace qTbot { /** @@ -22,17 +27,85 @@ class QTBOT_EXPORT iRequest public: iRequest(); + /** + * @brief RequestMethod Tgis islist of supported requests types of the requests. + */ + enum RequestMethod { + /// general ger request, all request data sent as a url line + Get, + /// general post request + Post, + /// this is post request to upload a big data to telegram + Upload + }; + /** * @brief makeUpload This method prepare data to upload; * @return data array prepared to sending. */ - virtual QString makeUpload() const = 0; + virtual QString makeUpload() const; /** * @brief baseAddress This method return base domain of remote server. * @return base domain name of remoute server. */ virtual QString baseAddress() const = 0; + + /** + * @brief method returns method of the request. + * @return method of the request + */ + virtual RequestMethod method() const = 0; + + /** + * @brief request return current requests commnad. + * @return current requests commnad. + */ + const QString& request() const; + + /** + * @brief setRequest sets custom requests commnad + * @param newRequest new custom commnad of the request. + */ + void setRequest(const QString &newRequest); + + /** + * @brief args This method returns a current list of arguments + * @return current list of arguments + */ + const QMap<QString, QVariant> &args() const; + + /** + * @brief addArg This method push new arg, to arguments list + * @param key This is new argument key + * @param val this is new argument value. + */ + void addArg(const QString& key, const QVariant& val); + + /** + * @brief setArgs For the some requests list of arguments posible to build only after constructor. + * @param newArgs This is new list of arguments. + */ + void setArgs(const QMap<QString, QVariant> &newArgs); + + /** + * @brief argsToUrl + * This method converts the arguments to a URL string. + * @return URL string created from the arguments. + */ + QString argsToUrl() const; + + /** + * @brief argsToMultipartFormData + * This method generates multipart/form-data request data. + * + * @return QHttpMultiPart - A QHttpMultiPart object containing multipart/form-data request data. + */ + QHttpMultiPart argsToMultipartFormData() const; +private: + QString _request; + QMap<QString, QVariant> _args; + }; } diff --git a/src/qTbot/src/public/qTbot/itelegrambot.cpp b/src/qTbot/src/public/qTbot/itelegrambot.cpp index 316cb2a..4f23282 100644 --- a/src/qTbot/src/public/qTbot/itelegrambot.cpp +++ b/src/qTbot/src/public/qTbot/itelegrambot.cpp @@ -47,7 +47,7 @@ bool ITelegramBot::login(const QByteArray &token) { setToken(token); - _loginReplay = sendRequest(QSharedPointer<TelegramGetMe>::create()); + _loginReplay = sendGetRequest(QSharedPointer<TelegramGetMe>::create()); if (_loginReplay) { connect(_loginReplay.get(), &QNetworkReply::finished, this, &ITelegramBot::handleLogin, @@ -88,7 +88,7 @@ bool ITelegramBot::sendSpecificMessage(const QVariant & chatId, callBackQueryId, disableWebPagePreview); - return bool(sendRequest(msg)); + return bool(sendGetRequest(msg)); } bool ITelegramBot::sendSpecificMessageWithKeyboard(const QVariant &chatId, @@ -116,7 +116,7 @@ bool ITelegramBot::sendSpecificMessageWithKeyboard(const QVariant &chatId, callBackQueryId, disableWebPagePreview); - return bool(sendRequest(msg)); + return bool(sendGetRequest(msg)); } bool ITelegramBot::deleteMessage(const QVariant &chatId, const QVariant &messageId) { @@ -129,7 +129,7 @@ bool ITelegramBot::deleteMessage(const QVariant &chatId, const QVariant &message auto msg = QSharedPointer<TelegramDeleteMessage>::create(chatId, messageId); - return bool(sendRequest(msg)); + return bool(sendGetRequest(msg)); } bool ITelegramBot::editSpecificMessageWithKeyboard(const QVariant & messageId, @@ -158,7 +158,7 @@ bool ITelegramBot::editSpecificMessageWithKeyboard(const QVariant & messageId, onTimeKeyboard, keyboard)); - return bool(sendRequest(msg)); + return bool(sendGetRequest(msg)); } QMap<QString, QSharedPointer<QJsonObject>> @@ -237,7 +237,7 @@ bool ITelegramBot::editSpecificMessageWithKeyboard(const QVariant &messageId, prepareInlineKeyBoard(keyboard)); - return bool(sendRequest(msg)); + return bool(sendGetRequest(msg)); } bool ITelegramBot::editSpecificMessage(const QVariant &messageId, @@ -265,7 +265,7 @@ bool ITelegramBot::editSpecificMessage(const QVariant &messageId, ); - return bool(sendRequest(msg)); + return bool(sendGetRequest(msg)); } bool ITelegramBot::sendSpecificMessageWithKeyboard(const QVariant &chatId, @@ -291,7 +291,7 @@ bool ITelegramBot::sendSpecificMessageWithKeyboard(const QVariant &chatId, callBackQueryId, disableWebPagePreview); - return bool(sendRequest(msg)); + return bool(sendGetRequest(msg)); } QSharedPointer<iFile> ITelegramBot::getFile(const QString &fileId, iFile::Type fileType) { @@ -339,7 +339,7 @@ QSharedPointer<iFile> ITelegramBot::getFile(const QString &fileId, iFile::Type f if (localFilePath.isEmpty()) return result; - if (auto &&replay = sendRequest(msg)) { + if (auto &&replay = sendGetRequest(msg)) { // here i must be receive responce and prepare new request to file from the call back function. if (fileType == iFile::Ram) { result = QSharedPointer<VirtualFile>::create(replay); @@ -366,7 +366,7 @@ QSharedPointer<iFile> ITelegramBot::getFile(const QString &fileId, iFile::Type f QSharedPointer<QNetworkReply> ITelegramBot::getFileMeta(const QString &fileId, const QWeakPointer<iFile>& receiver) { auto msg = QSharedPointer<TelegramGetFile>::create(fileId); - if (auto&& ptr = sendRequest(msg)) { + if (auto&& ptr = sendGetRequest(msg)) { connect(ptr.get(), &QNetworkReply::finished, this, std::bind(&ITelegramBot::handleFileHeader, this, ptr.toWeakRef(), receiver)); @@ -472,7 +472,7 @@ void ITelegramBot::handleFileHeader(const QWeakPointer<QNetworkReply> &sender, if (auto&& sharedPtr = receiver.lock()) { auto&& downloadRequest = QSharedPointer<TelegrammDownloadFile>::create(fileMetaInfo->takePath()); - sharedPtr->setDownloadRequest(sendRequest(downloadRequest)); + sharedPtr->setDownloadRequest(sendGetRequest(downloadRequest)); } } } diff --git a/src/qTbot/src/public/qTbot/telegramrestbot.cpp b/src/qTbot/src/public/qTbot/telegramrestbot.cpp index 10d8fb9..d97685d 100644 --- a/src/qTbot/src/public/qTbot/telegramrestbot.cpp +++ b/src/qTbot/src/public/qTbot/telegramrestbot.cpp @@ -39,7 +39,7 @@ void TelegramRestBot::startUpdates() { if (delta >= _updateDelay) { - auto&& replay = sendRequest(QSharedPointer<TelegramGetUpdate>::create()); + auto&& replay = sendGetRequest(QSharedPointer<TelegramGetUpdate>::create()); connect(replay.get(), &QNetworkReply::finished, this, std::bind(&TelegramRestBot::handleReceiveUpdates, this, replay.toWeakRef()),