added support of post reqeusts (still not work)

This commit is contained in:
Andrei Yankovich 2023-10-22 12:25:22 +02:00
parent b6c6ace955
commit 02a41d547f
11 changed files with 228 additions and 101 deletions

View File

@ -8,8 +8,39 @@
namespace qTbot { namespace qTbot {
TelegramSendDocument::TelegramSendDocument() : TelegramSendDocument::TelegramSendDocument(const QVariant &chatId,
const QString &text,
const QString& fileName,
const QByteArray &data):
TelegramSingleRquest("sendDocument") { TelegramSingleRquest("sendDocument") {
addArg("chat_id", chatId);
if (text.size())
addArg("text", text);
addArg(REQUEST_UPLOAD_FILE_KEY, fileName.toLatin1() + ":" + data);
}
TelegramSendDocument::TelegramSendDocument(const QVariant &chatId,
const QString &text,
const QFileInfo &file):
TelegramSingleRquest("sendDocument")
{
addArg("chat_id", chatId);
if (text.size())
addArg("text", text);
QFile readFile(file.absoluteFilePath());
if (!readFile.open(QIODevice::ReadOnly)) {
qWarning() << "Fail to open file" << file.absoluteFilePath();
}
addArg(REQUEST_UPLOAD_FILE_KEY, file.completeBaseName().toLatin1() + ":" + readFile.readAll());
}
iRequest::RequestMethod TelegramSendDocument::method() const {
return Upload;
} }
} }

View File

@ -10,6 +10,9 @@
#include "telegramsinglerquest.h" #include "telegramsinglerquest.h"
#include <QFile>
#include <QFileInfo>
namespace qTbot { namespace qTbot {
/** /**
@ -18,7 +21,19 @@ namespace qTbot {
class TelegramSendDocument: public TelegramSingleRquest class TelegramSendDocument: public TelegramSingleRquest
{ {
public: public:
TelegramSendDocument(); TelegramSendDocument(const QVariant &chatId,
const QString &text,
const QString &fileName,
const QByteArray& data);
TelegramSendDocument(const QVariant &chatId,
const QString &text,
const QFileInfo &file);
// iRequest interface
public:
RequestMethod method() const override;
}; };
} }
#endif // TELEGRAMSENDDOCUMENT_H #endif // TELEGRAMSENDDOCUMENT_H

View File

@ -27,4 +27,8 @@ QString TelegramSingleRquest::baseAddress() const {
return "https://api.telegram.org"; return "https://api.telegram.org";
} }
iRequest::RequestMethod TelegramSingleRquest::method() const {
return Get;
}
} }

View File

@ -43,7 +43,6 @@ public:
*/ */
TelegramSingleRquest(const QString &request, const QMap<QString, QVariant> &args); TelegramSingleRquest(const QString &request, const QMap<QString, QVariant> &args);
/** /**
* @brief TelegramSingleRquest This main constructor of the single requests. * @brief TelegramSingleRquest This main constructor of the single requests.
* @param request This is request name (command) * @param request This is request name (command)
@ -51,7 +50,7 @@ public:
TelegramSingleRquest(const QString& request); TelegramSingleRquest(const QString& request);
QString baseAddress() const override; QString baseAddress() const override;
RequestMethod method() const override;
}; };
} }

View File

@ -45,7 +45,7 @@ void IBot::incomeNewUpdate(const QSharedPointer<iUpdate> &message) {
} }
QSharedPointer<QNetworkReply> QSharedPointer<QNetworkReply>
IBot::sendRequest(const QSharedPointer<iRequest> &rquest, RequestMethod method) { IBot::sendRequest(const QSharedPointer<iRequest> &rquest) {
if (!rquest) if (!rquest)
return nullptr; return nullptr;
@ -58,22 +58,28 @@ IBot::sendRequest(const QSharedPointer<iRequest> &rquest, RequestMethod method)
#endif #endif
QSharedPointer<QNetworkReply> networkReplay; QSharedPointer<QNetworkReply> networkReplay;
QSharedPointer<QHttpMultiPart> httpData;
switch (method) { switch (rquest->method()) {
case Get: case iRequest::Get:
networkReplay.reset(_manager->get(QNetworkRequest(url))); networkReplay.reset(_manager->get(QNetworkRequest(url)));
break; break;
case Post: case iRequest::Post:
// req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); // req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
// reply = m_nam.post(req, params.toByteArray()); // reply = m_nam.post(req, params.toByteArray());
// break; // break;
case Upload: case iRequest::Upload:
QByteArray boundary = params.toMultipartBoundary(); QNetworkRequest netRequest(url);
req.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary=" + boundary); netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("multipart/form-data"));
QByteArray requestData = params.generateMultipartFormData(boundary);
req.setHeader(QNetworkRequest::ContentLengthHeader, requestData.length()); httpData = rquest->argsToMultipartFormData();
reply = m_nam.post(req, requestData); if (httpData) {
networkReplay.reset(_manager->post(netRequest, httpData.data()));
} else {
return nullptr;
}
break; break;
} }
@ -81,7 +87,7 @@ IBot::sendRequest(const QSharedPointer<iRequest> &rquest, RequestMethod method)
_replayStorage[address] = networkReplay; _replayStorage[address] = networkReplay;
connect(networkReplay.get(), &QNetworkReply::finished, this, connect(networkReplay.get(), &QNetworkReply::finished, this,
[this, address]() { [this, address, httpData]() {
_toRemove.push_back(address); _toRemove.push_back(address);
}); });
@ -89,7 +95,16 @@ IBot::sendRequest(const QSharedPointer<iRequest> &rquest, RequestMethod method)
[this, address](QNetworkReply::NetworkError err){ [this, address](QNetworkReply::NetworkError err){
qWarning() << "The reqeust " << address << " finished with error code : " << err; qWarning() << "The reqeust " << address << " finished with error code : " << err;
if (auto&& replay = _replayStorage.value(address)) { if (auto&& replay = _replayStorage.value(address)) {
qWarning() << "Server ansver: " << replay->readAll(); qWarning() << "Server ansver: " << replay->readAll() << "request: ";
auto request = replay->request();
QUrl url = request.url();
qDebug() << "URL: " << url.toString();
QList<QByteArray> headers = request.rawHeaderList();
qDebug() << "rquest headers:";
foreach (QByteArray header, headers) {
qDebug() << header << ": " << request.rawHeader(header);
}
} }
_toRemove.push_back(address); _toRemove.push_back(address);

View File

@ -14,6 +14,7 @@
#include "qTbot/irequest.h" #include "qTbot/irequest.h"
#include "ifile.h" #include "ifile.h"
#include "qfileinfo.h"
#include <QMap> #include <QMap>
#include <QHash> #include <QHash>
@ -80,7 +81,7 @@ public:
* @param chatId id of the chat. * @param chatId id of the chat.
* @return Returns true if the file sents successful. * @return Returns true if the file sents successful.
*/ */
virtual bool sendFile( const QFile& file, const QVariant& chatId) = 0; virtual bool sendFile( const QFileInfo& file, const QVariant& chatId) = 0;
/** /**
* @brief sendFile This method setns a file that saved as a bytearray. * @brief sendFile This method setns a file that saved as a bytearray.
@ -168,11 +169,11 @@ protected:
/** /**
* @brief sendRequest This method sent custom requests to the server. * @brief sendRequest This method sent custom requests to the server.
* @param rquest This is message that will be sent to 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. * @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. * @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, RequestMethod method = RequestMethod::Get); QSharedPointer<QNetworkReply>
sendRequest(const QSharedPointer<iRequest>& rquest);
/** /**
* @brief setToken This is setter of the IBot::token value. * @brief setToken This is setter of the IBot::token value.

View File

@ -55,37 +55,38 @@ QString iRequest::argsToUrl() const {
return args; return args;
} }
QHttpMultiPart iRequest::argsToMultipartFormData() const { QSharedPointer<QHttpMultiPart> iRequest::argsToMultipartFormData() const {
QHttpMultiPart multiPart(QHttpMultiPart::FormDataType); QSharedPointer<QHttpMultiPart> multiPart = QSharedPointer<QHttpMultiPart>::create(QHttpMultiPart::FormDataType);
auto it = _args.constBegin(); auto it = _args.constBegin();
while (it != _args.constEnd()) { while (it != _args.constEnd()) {
QHttpPart part; QHttpPart part;
auto && value = it.value(); auto && value = it.value();
if (value.typeId() == QMetaType::QByteArray) {
if (it.key() == REQUEST_UPLOAD_FILE_KEY) {
QByteArray && array = value.toByteArray(); QByteArray && array = value.toByteArray();
if (array.left(5) == "file:") {
const auto metaData = array.split(':'); const auto metaData = array.split(':');
if (metaData.size() == 3) { if (metaData.size() == 2) {
const auto fileName = metaData[1]; const auto fileName = metaData[0];
const QByteArray fileData = metaData[2]; const QByteArray fileData = metaData[1];
part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"document\"; filename=\"" + fileName + "\"")); part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"document\"; filename=\"" + fileName + "\""));
part.setBody(fileData); part.setBody(fileData);
} else { } else {
qWarning() << "the file arguments must be like file:fileName:Data"; qWarning() << "the file arguments must be like file:fileName:Data";
return nullptr;
} }
} else { } else {
part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + it.key() + "\"")); part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + it.key() + "\""));
part.setBody(it.value().toByteArray()); part.setBody(it.value().toByteArray());
} }
} multiPart->append(part);
multiPart.append(part);
++it; ++it;
} }
multiPart.append(chatIdPart);
return multiPart;
} }
const QString& iRequest::request() const { const QString& iRequest::request() const {

View File

@ -16,6 +16,7 @@
#include <QString> #include <QString>
#include <QHttpMultiPart> #include <QHttpMultiPart>
#define REQUEST_UPLOAD_FILE_KEY "file"
namespace qTbot { namespace qTbot {
/** /**
@ -101,7 +102,7 @@ public:
* *
* @return QHttpMultiPart - A QHttpMultiPart object containing multipart/form-data request data. * @return QHttpMultiPart - A QHttpMultiPart object containing multipart/form-data request data.
*/ */
QHttpMultiPart argsToMultipartFormData() const; QSharedPointer<QHttpMultiPart> argsToMultipartFormData() const;
private: private:
QString _request; QString _request;
QMap<QString, QVariant> _args; QMap<QString, QVariant> _args;

View File

@ -10,6 +10,7 @@
#include "file.h" #include "file.h"
#include "requests/telegrammdownloadfile.h" #include "requests/telegrammdownloadfile.h"
#include "qdir.h" #include "qdir.h"
#include "requests/telegramsenddocument.h"
#include "virtualfile.h" #include "virtualfile.h"
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
@ -47,7 +48,7 @@ bool ITelegramBot::login(const QByteArray &token) {
setToken(token); setToken(token);
_loginReplay = sendGetRequest(QSharedPointer<TelegramGetMe>::create()); _loginReplay = sendRequest(QSharedPointer<TelegramGetMe>::create());
if (_loginReplay) { if (_loginReplay) {
connect(_loginReplay.get(), &QNetworkReply::finished, connect(_loginReplay.get(), &QNetworkReply::finished,
this, &ITelegramBot::handleLogin, this, &ITelegramBot::handleLogin,
@ -88,7 +89,7 @@ bool ITelegramBot::sendSpecificMessage(const QVariant & chatId,
callBackQueryId, callBackQueryId,
disableWebPagePreview); disableWebPagePreview);
return bool(sendGetRequest(msg)); return bool(sendRequest(msg));
} }
bool ITelegramBot::sendSpecificMessageWithKeyboard(const QVariant &chatId, bool ITelegramBot::sendSpecificMessageWithKeyboard(const QVariant &chatId,
@ -116,7 +117,7 @@ bool ITelegramBot::sendSpecificMessageWithKeyboard(const QVariant &chatId,
callBackQueryId, callBackQueryId,
disableWebPagePreview); disableWebPagePreview);
return bool(sendGetRequest(msg)); return bool(sendRequest(msg));
} }
bool ITelegramBot::deleteMessage(const QVariant &chatId, const QVariant &messageId) { bool ITelegramBot::deleteMessage(const QVariant &chatId, const QVariant &messageId) {
@ -129,7 +130,7 @@ bool ITelegramBot::deleteMessage(const QVariant &chatId, const QVariant &message
auto msg = QSharedPointer<TelegramDeleteMessage>::create(chatId, auto msg = QSharedPointer<TelegramDeleteMessage>::create(chatId,
messageId); messageId);
return bool(sendGetRequest(msg)); return bool(sendRequest(msg));
} }
bool ITelegramBot::editSpecificMessageWithKeyboard(const QVariant & messageId, bool ITelegramBot::editSpecificMessageWithKeyboard(const QVariant & messageId,
@ -158,7 +159,7 @@ bool ITelegramBot::editSpecificMessageWithKeyboard(const QVariant & messageId,
onTimeKeyboard, onTimeKeyboard,
keyboard)); keyboard));
return bool(sendGetRequest(msg)); return bool(sendRequest(msg));
} }
QMap<QString, QSharedPointer<QJsonObject>> QMap<QString, QSharedPointer<QJsonObject>>
@ -237,7 +238,7 @@ bool ITelegramBot::editSpecificMessageWithKeyboard(const QVariant &messageId,
prepareInlineKeyBoard(keyboard)); prepareInlineKeyBoard(keyboard));
return bool(sendGetRequest(msg)); return bool(sendRequest(msg));
} }
bool ITelegramBot::editSpecificMessage(const QVariant &messageId, bool ITelegramBot::editSpecificMessage(const QVariant &messageId,
@ -265,7 +266,7 @@ bool ITelegramBot::editSpecificMessage(const QVariant &messageId,
); );
return bool(sendGetRequest(msg)); return bool(sendRequest(msg));
} }
bool ITelegramBot::sendSpecificMessageWithKeyboard(const QVariant &chatId, bool ITelegramBot::sendSpecificMessageWithKeyboard(const QVariant &chatId,
@ -291,7 +292,7 @@ bool ITelegramBot::sendSpecificMessageWithKeyboard(const QVariant &chatId,
callBackQueryId, callBackQueryId,
disableWebPagePreview); disableWebPagePreview);
return bool(sendGetRequest(msg)); return bool(sendRequest(msg));
} }
QSharedPointer<iFile> ITelegramBot::getFile(const QString &fileId, iFile::Type fileType) { QSharedPointer<iFile> ITelegramBot::getFile(const QString &fileId, iFile::Type fileType) {
@ -339,7 +340,7 @@ QSharedPointer<iFile> ITelegramBot::getFile(const QString &fileId, iFile::Type f
if (localFilePath.isEmpty()) if (localFilePath.isEmpty())
return result; return result;
if (auto &&replay = sendGetRequest(msg)) { if (auto &&replay = sendRequest(msg)) {
// here i must be receive responce and prepare new request to file from the call back function. // here i must be receive responce and prepare new request to file from the call back function.
if (fileType == iFile::Ram) { if (fileType == iFile::Ram) {
result = QSharedPointer<VirtualFile>::create(replay); result = QSharedPointer<VirtualFile>::create(replay);
@ -366,7 +367,7 @@ QSharedPointer<iFile> ITelegramBot::getFile(const QString &fileId, iFile::Type f
QSharedPointer<QNetworkReply> ITelegramBot::getFileMeta(const QString &fileId, const QWeakPointer<iFile>& receiver) { QSharedPointer<QNetworkReply> ITelegramBot::getFileMeta(const QString &fileId, const QWeakPointer<iFile>& receiver) {
auto msg = QSharedPointer<TelegramGetFile>::create(fileId); auto msg = QSharedPointer<TelegramGetFile>::create(fileId);
if (auto&& ptr = sendGetRequest(msg)) { if (auto&& ptr = sendRequest(msg)) {
connect(ptr.get(), &QNetworkReply::finished, connect(ptr.get(), &QNetworkReply::finished,
this, std::bind(&ITelegramBot::handleFileHeader, this, ptr.toWeakRef(), receiver)); this, std::bind(&ITelegramBot::handleFileHeader, this, ptr.toWeakRef(), receiver));
@ -376,7 +377,38 @@ QSharedPointer<QNetworkReply> ITelegramBot::getFileMeta(const QString &fileId, c
return nullptr; return nullptr;
} }
bool ITelegramBot::sendFile(const QFile &file, const QVariant &chatId) { bool ITelegramBot::sendFile(const QFileInfo &file, const QVariant &chatId) {
return sendFileWithDescription(file, chatId, "");
}
bool ITelegramBot::sendFile(const QByteArray &file, const QString &fileName, const QVariant &chatId) {
return sendFileWithDescription(file, fileName, chatId, "");
}
bool ITelegramBot::sendFileWithDescription(const QByteArray &file,
const QString &fileName,
const QVariant &chatId,
const QString &description) {
if (!chatId.isValid() || chatId.isNull())
return false;
if (!fileName.size()) {
return false;
}
if (!file.size()) {
return false;
}
auto&& request = QSharedPointer<TelegramSendDocument>::create(chatId, description, fileName, file);
return bool(sendRequest(request));
}
bool ITelegramBot::sendFileWithDescription(const QFileInfo &file,
const QVariant &chatId,
const QString &description) {
if (!chatId.isValid() || chatId.isNull()) if (!chatId.isValid() || chatId.isNull())
return false; return false;
@ -384,14 +416,19 @@ bool ITelegramBot::sendFile(const QFile &file, const QVariant &chatId) {
return false; return false;
} }
auto&& request = QSharedPointer<TelegramSendDocument>::create(chatId, description, file);
} return bool(sendRequest(request));
bool ITelegramBot::sendFile(const QByteArray &file, const QString &fileName, const QVariant &chatId) {
} }
bool ITelegramBot::sendFileById(const QString &fileID, const QVariant &chatId) { bool ITelegramBot::sendFileById(const QString &fileID, const QVariant &chatId) {
Q_UNUSED(fileID)
Q_UNUSED(chatId)
throw "the sendFileById is not implemented";
return false;
} }
@ -472,7 +509,7 @@ void ITelegramBot::handleFileHeader(const QWeakPointer<QNetworkReply> &sender,
if (auto&& sharedPtr = receiver.lock()) { if (auto&& sharedPtr = receiver.lock()) {
auto&& downloadRequest = QSharedPointer<TelegrammDownloadFile>::create(fileMetaInfo->takePath()); auto&& downloadRequest = QSharedPointer<TelegrammDownloadFile>::create(fileMetaInfo->takePath());
sharedPtr->setDownloadRequest(sendGetRequest(downloadRequest)); sharedPtr->setDownloadRequest(sendRequest(downloadRequest));
} }
} }
} }

View File

@ -223,10 +223,33 @@ public:
QSharedPointer<QNetworkReply> getFileMeta(const QString& fileId, QSharedPointer<QNetworkReply> getFileMeta(const QString& fileId,
const QWeakPointer<iFile> &receiver = {nullptr}); const QWeakPointer<iFile> &receiver = {nullptr});
bool sendFile( const QFile& file, const QVariant& chatId) override; bool sendFile( const QFileInfo& file, const QVariant& chatId) override;
bool sendFile( const QByteArray& file, const QString& fileName, const QVariant& chatId) override; bool sendFile( const QByteArray& file, const QString& fileName, const QVariant& chatId) override;
/**
* @brief sendFileWithDescription This method sents a byte array as a file into @a chatId with additional text @a description.
* @param file This is a file source
* @param fileName This is a dispalyed name of file.
* @param chatId This is distanation id chat.
* @param description additional text for message.
* @return true if the message sents successful else false.
*/
bool sendFileWithDescription( const QByteArray& file,
const QString& fileName,
const QVariant& chatId,
const QString& description);
/**
* @brief sendFileWithDescription This method sents a byte array as a file into @a chatId with additional text @a description.
* @param file This is a file source
* @param chatId This is distanation id chat.
* @param description additional text for message.
* @return true if the message sents successful else false.
*/
bool sendFileWithDescription( const QFileInfo& file,
const QVariant& chatId,
const QString& description);
/** /**
* @brief sendFileById This is specific method of the telegram bot. sents file by id. * @brief sendFileById This is specific method of the telegram bot. sents file by id.
* @param fileID This is file id. * @param fileID This is file id.

View File

@ -39,7 +39,7 @@ void TelegramRestBot::startUpdates() {
if (delta >= _updateDelay) { if (delta >= _updateDelay) {
auto&& replay = sendGetRequest(QSharedPointer<TelegramGetUpdate>::create()); auto&& replay = sendRequest(QSharedPointer<TelegramGetUpdate>::create());
connect(replay.get(), &QNetworkReply::finished, connect(replay.get(), &QNetworkReply::finished,
this, std::bind(&TelegramRestBot::handleReceiveUpdates, this, replay.toWeakRef()), this, std::bind(&TelegramRestBot::handleReceiveUpdates, this, replay.toWeakRef()),