diff --git a/src/qTbot/src/private/requests/telegramsenddocument.cpp b/src/qTbot/src/private/requests/telegramsenddocument.cpp index 25fd992..85e2135 100644 --- a/src/qTbot/src/private/requests/telegramsenddocument.cpp +++ b/src/qTbot/src/private/requests/telegramsenddocument.cpp @@ -12,35 +12,11 @@ TelegramSendDocument::TelegramSendDocument(const QVariant &chatId, const QString &text, const QString& fileName, const QByteArray &data): - TelegramSingleRquest("sendDocument") { - - addArg("chat_id", chatId); - if (text.size()) - addArg("caption", text); - - addArg(QString("%0:%1").arg(REQUEST_UPLOAD_FILE_KEY, fileName), data); - -} + TelegramSendFile("sendDocument", chatId, text, fileName, TELEGRAM_DOCUMENT, data) {} TelegramSendDocument::TelegramSendDocument(const QVariant &chatId, const QString &text, const QFileInfo &file): - TelegramSingleRquest("sendDocument") -{ - addArg("chat_id", chatId); + TelegramSendFile("sendDocument", chatId, text, file) {} - 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; -} } diff --git a/src/qTbot/src/private/requests/telegramsenddocument.h b/src/qTbot/src/private/requests/telegramsenddocument.h index 4e62e7a..7bd389a 100644 --- a/src/qTbot/src/private/requests/telegramsenddocument.h +++ b/src/qTbot/src/private/requests/telegramsenddocument.h @@ -8,17 +8,15 @@ #ifndef TELEGRAMSENDDOCUMENT_H #define TELEGRAMSENDDOCUMENT_H -#include "telegramsinglerquest.h" +#include "telegramsendfile.h" -#include <QFile> -#include <QFileInfo> namespace qTbot { /** * @brief The TelegramSendDocument class sents document into chat */ -class TelegramSendDocument: public TelegramSingleRquest +class TelegramSendDocument: public TelegramSendFile { public: TelegramSendDocument(const QVariant &chatId, @@ -30,10 +28,6 @@ public: const QString &text, const QFileInfo &file); - - // iRequest interface -public: - RequestMethod method() const override; }; } #endif // TELEGRAMSENDDOCUMENT_H diff --git a/src/qTbot/src/private/requests/telegramsendfile.cpp b/src/qTbot/src/private/requests/telegramsendfile.cpp new file mode 100644 index 0000000..3b6af0e --- /dev/null +++ b/src/qTbot/src/private/requests/telegramsendfile.cpp @@ -0,0 +1,85 @@ +//# +//# Copyright (C) 2023-2023 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# +#include "telegramsendfile.h" + +#include <QJsonDocument> + +namespace qTbot { + + +qTbot::TelegramSendFile::TelegramSendFile(const QString &request, + const QVariant &chatId, + const QString &text, + const QString &fileName, + const QString &fileType, + const QByteArray &data, + unsigned long long replyToMessageId, + const QMap<QString, QSharedPointer<QJsonObject>>& extraObjects + ): + TelegramSingleRquest(request) { + + addArg("chat_id", chatId); + if (text.size()) + addArg("caption", text); + + if (replyToMessageId > 0) { + addArg("reply_to_message_id", replyToMessageId); + } + + for (auto it = extraObjects.begin(); it != extraObjects.end(); it = std::next(it)) { + addArg(it.key(), QJsonDocument(*it.value()).toJson(QJsonDocument::Compact)); + } + + addArg(QString("%0:%1:%2").arg(REQUEST_UPLOAD_FILE_KEY, fileName, fileType), data); +} + +qTbot::TelegramSendFile::TelegramSendFile(const QString &request, + const QVariant &chatId, + const QString &text, + const QFileInfo &file, + unsigned long long replyToMessageId, + const QMap<QString, QSharedPointer<QJsonObject> > &extraObjects): + TelegramSingleRquest(request) { + + addArg("chat_id", chatId); + + if (text.size()) + addArg("text", text); + + if (replyToMessageId > 0) { + addArg("reply_to_message_id", replyToMessageId); + } + + QFile readFile(file.absoluteFilePath()); + if (!readFile.open(QIODevice::ReadOnly)) { + qWarning() << "Fail to open file" << file.absoluteFilePath(); + } + + for (auto it = extraObjects.begin(); it != extraObjects.end(); it = std::next(it)) { + addArg(it.key(), QJsonDocument(*it.value()).toJson(QJsonDocument::Compact)); + } + + auto&& sufix = file.suffix(); + if (sufix.contains("png") || sufix.contains("jpg") || sufix.contains("jepg") || sufix.contains("gif")) { + addArg(QString("%0:%1:%2").arg(REQUEST_UPLOAD_FILE_KEY, file.fileName(), TELEGRAM_PHOTO), readFile.readAll()); + + } else { + addArg(QString("%0:%1:%2").arg(REQUEST_UPLOAD_FILE_KEY, file.fileName(), TELEGRAM_DOCUMENT), readFile.readAll()); + + } + + readFile.close(); +} + +iRequest::RequestMethod TelegramSendFile::method() const { + return iRequest::RequestMethod::Upload; +} + +QString TelegramSendFile::type() const { + return REQUEST_UPLOAD_FILE_KEY; +} +} diff --git a/src/qTbot/src/private/requests/telegramsendfile.h b/src/qTbot/src/private/requests/telegramsendfile.h new file mode 100644 index 0000000..e0d0596 --- /dev/null +++ b/src/qTbot/src/private/requests/telegramsendfile.h @@ -0,0 +1,51 @@ +//# +//# Copyright (C) 2023-2023 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# +#ifndef TELEGRAMSENDFILE_H +#define TELEGRAMSENDFILE_H + +#include "qfileinfo.h" +#include "requests/telegramsinglerquest.h" + +#define TELEGRAM_PHOTO "photo" +#define TELEGRAM_DOCUMENT "document" + +namespace qTbot { + +/** + * @brief The TelegramSendFile class Base clas for upload files to server + */ +class TelegramSendFile: public TelegramSingleRquest +{ +public: + + TelegramSendFile(const QString &request, + const QVariant &chatId, + const QString &text, + const QString &fileName, + const QString &fileType, + const QByteArray& data, + unsigned long long replyToMessageId = 0, + const QMap<QString, QSharedPointer<QJsonObject> > &extraObjects = {}); + + TelegramSendFile(const QString &request, + const QVariant &chatId, + const QString &text, + const QFileInfo &file, + unsigned long long replyToMessageId = 0, + const QMap<QString, QSharedPointer<QJsonObject> > &extraObjects = {}); + + RequestMethod method() const override; + +protected: + /** + * @brief type return type file. By Default it is REQUEST_UPLOAD_FILE_KEY + * @return + */ + virtual QString type() const; +}; +} +#endif // TELEGRAMSENDFILE_H diff --git a/src/qTbot/src/private/requests/telegramsendphoto.cpp b/src/qTbot/src/private/requests/telegramsendphoto.cpp new file mode 100644 index 0000000..2033602 --- /dev/null +++ b/src/qTbot/src/private/requests/telegramsendphoto.cpp @@ -0,0 +1,34 @@ +//# +//# Copyright (C) 2023-2023 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "telegramsendphoto.h" + +namespace qTbot { + + +TelegramSendPhoto::TelegramSendPhoto(const QVariant &chatId, + const QString &text, + const QString &fileName, + const QByteArray &data, + unsigned long long replyToMessageId, + const QMap<QString, QSharedPointer<QJsonObject>>& extraObjects + ): + TelegramSendFile("sendPhoto", chatId, text, fileName, TELEGRAM_PHOTO, data, replyToMessageId, extraObjects) { + +} + +TelegramSendPhoto::TelegramSendPhoto(const QVariant &chatId, + const QString &text, + const QFileInfo &file, + unsigned long long replyToMessageId, + const QMap<QString, QSharedPointer<QJsonObject> > &extraObjects): + TelegramSendFile("sendPhoto", chatId, text, file, replyToMessageId, extraObjects) { + +} + +} diff --git a/src/qTbot/src/private/requests/telegramsendphoto.h b/src/qTbot/src/private/requests/telegramsendphoto.h new file mode 100644 index 0000000..1f7eac7 --- /dev/null +++ b/src/qTbot/src/private/requests/telegramsendphoto.h @@ -0,0 +1,39 @@ +//# +//# Copyright (C) 2023-2023 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef TELEGRAMSENDPHOTO_H +#define TELEGRAMSENDPHOTO_H + +#include "telegramsendfile.h" + +namespace qTbot { + +/** + * @brief The TelegramSendPhoto class using to sending photos on chat + */ +class TelegramSendPhoto: public TelegramSendFile +{ +public: + TelegramSendPhoto(const QVariant &chatId, + const QString &text, + const QString &fileName, + const QByteArray& data, + unsigned long long replyToMessageId = 0, + const QMap<QString, QSharedPointer<QJsonObject>>& extraObjects = {} + ); + + TelegramSendPhoto(const QVariant &chatId, + const QString &text, + const QFileInfo &file, + unsigned long long replyToMessageId = 0, + const QMap<QString, QSharedPointer<QJsonObject>>& extraObjects = {} + ); + +}; +} +#endif // TELEGRAMSENDPHOTO_H diff --git a/src/qTbot/src/public/qTbot/irequest.cpp b/src/qTbot/src/public/qTbot/irequest.cpp index f3bbffa..92972ae 100644 --- a/src/qTbot/src/public/qTbot/irequest.cpp +++ b/src/qTbot/src/public/qTbot/irequest.cpp @@ -66,13 +66,16 @@ QSharedPointer<QHttpMultiPart> iRequest::argsToMultipartFormData() const { if (it.key().contains(REQUEST_UPLOAD_FILE_KEY)) { auto metaData = it.key().split(":"); - if (metaData.size() == 2) { + if (metaData.size() == 3) { const auto fileName = metaData[1]; - part.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"document\"; filename=\"" + fileName + "\""); + const auto fileType = metaData[2]; + + part.setHeader(QNetworkRequest::ContentDispositionHeader, + "form-data; name=\"" + fileType + "\"; filename=\"" + fileName + "\""); part.setBody(value.toByteArray()); } else { - qWarning() << "the file arguments must be like _file_:fileName"; + qWarning() << "the file arguments must be like _file_:fileName:fileType"; return nullptr; } diff --git a/src/qTbot/src/public/qTbot/irequest.h b/src/qTbot/src/public/qTbot/irequest.h index 1574732..33b10d0 100644 --- a/src/qTbot/src/public/qTbot/irequest.h +++ b/src/qTbot/src/public/qTbot/irequest.h @@ -17,6 +17,7 @@ #include <QHttpMultiPart> #define REQUEST_UPLOAD_FILE_KEY "_file_" + namespace qTbot { /** diff --git a/src/qTbot/src/public/qTbot/itelegrambot.cpp b/src/qTbot/src/public/qTbot/itelegrambot.cpp index 0d594eb..5545187 100644 --- a/src/qTbot/src/public/qTbot/itelegrambot.cpp +++ b/src/qTbot/src/public/qTbot/itelegrambot.cpp @@ -20,6 +20,7 @@ #include <requests/telegramdeletemessage.h> #include <requests/telegrameditmessage.h> #include <requests/telegramsendlocation.h> +#include <requests/telegramsendphoto.h> #include <QNetworkReply> #include <QSharedPointer> @@ -106,10 +107,6 @@ bool ITelegramBot::sendSpecificMessageWithKeyboard(const QVariant &chatId, if (!chatId.isValid() || chatId.isNull()) return false; - if (text.isEmpty()) { - return false; - } - auto msg = QSharedPointer<TelegramSendMsg>::create(chatId, text, prepareKeyboard(autoResizeKeyboard, onTimeKeyboard, keyboard), @@ -221,7 +218,7 @@ bool ITelegramBot::editSpecificMessageWithKeyboard(const QVariant &messageId, const QString &text, bool markdown, bool disableWebPagePreview, - const QList<QMap<QString, std::function<void (const QString &, const QVariant&)> > > &keyboard, + const KeyboardOnMessage &keyboard, const QString &callBackQueryId) { if (!chatId.isValid() || chatId.isNull()) @@ -386,6 +383,44 @@ bool ITelegramBot::sendFile(const QByteArray &file, const QString &fileName, con return sendFileWithDescription(file, fileName, chatId, ""); } +bool ITelegramBot::sendPhoto(const QFileInfo &photo, + const QVariant &chatId, + const QString &description, + unsigned long long replyToMessageId, + const KeyboardOnMessage &keyboard) { + if (!chatId.isValid() || chatId.isNull()) + return false; + + if (!photo.isReadable()) { + return false; + } + + return sendFileWithPrivate(QSharedPointer<TelegramSendPhoto>::create( + chatId, description, photo, replyToMessageId, prepareInlineKeyBoard(keyboard))); +} + +bool ITelegramBot::sendPhoto(const QByteArray &photo, + const QString &fileName, + const QVariant &chatId, + const QString &description, + unsigned long long replyToMessageId, + const KeyboardOnMessage &keyboard) { + + if (!chatId.isValid() || chatId.isNull()) + return false; + + if (!fileName.size()) { + return false; + } + + if (!photo.size()) { + return false; + } + + return sendFileWithPrivate(QSharedPointer<TelegramSendPhoto>::create( + chatId, description, fileName, photo, replyToMessageId, prepareInlineKeyBoard(keyboard))); +} + bool ITelegramBot::sendFileWithDescription(const QByteArray &file, const QString &fileName, const QVariant &chatId, @@ -402,9 +437,7 @@ bool ITelegramBot::sendFileWithDescription(const QByteArray &file, return false; } - auto&& request = QSharedPointer<TelegramSendDocument>::create(chatId, description, fileName, file); - - return bool(sendRequest(request)); + return sendFileWithPrivate(QSharedPointer<TelegramSendDocument>::create(chatId, description, fileName, file)); } bool ITelegramBot::sendFileWithDescription(const QFileInfo &file, @@ -417,10 +450,7 @@ bool ITelegramBot::sendFileWithDescription(const QFileInfo &file, return false; } - auto&& request = QSharedPointer<TelegramSendDocument>::create(chatId, description, file); - - return bool(sendRequest(request)); - + return sendFileWithPrivate(QSharedPointer<TelegramSendDocument>::create(chatId, description, file)); } bool ITelegramBot::sendFileById(const QString &fileID, const QVariant &chatId) { @@ -532,6 +562,10 @@ void ITelegramBot::handleFileHeader(const QWeakPointer<QNetworkReply> &sender, } } +bool ITelegramBot::sendFileWithPrivate(const QSharedPointer<TelegramSendFile> &file) { + return bool(sendRequest(file)); +} + QString ITelegramBot::findFileInlocatStorage(const QString &fileId) const { QDir defaultFileDir(defaultFileStorageLocation()); diff --git a/src/qTbot/src/public/qTbot/itelegrambot.h b/src/qTbot/src/public/qTbot/itelegrambot.h index 2b6a808..6d739bd 100644 --- a/src/qTbot/src/public/qTbot/itelegrambot.h +++ b/src/qTbot/src/public/qTbot/itelegrambot.h @@ -21,6 +21,7 @@ namespace qTbot { class ITelegramMessage; class TelegramFile; class TelegramUpdateAnswer; +class TelegramSendFile; typedef std::function<void(const QString& buttonKey, const QVariant& msgID)> ButtonCB; typedef QList<QMap<QString, ButtonCB >> KeyboardOnMessage; @@ -120,9 +121,9 @@ public: bool sendSpecificMessageWithKeyboard(const QVariant &chatId, const QString& text, const QList<QList<QString> > &keyboard, - const QString &callBackQueryId, + const QString &callBackQueryId = "", bool onTimeKeyboard = false, - bool autoResizeKeyboard = false, + bool autoResizeKeyboard = true, unsigned long long replyToMessageId = 0, bool markdown = true, bool disableWebPagePreview = false); @@ -186,7 +187,7 @@ public: const QString &text, bool markdown = true, bool disableWebPagePreview = false, - const QList<QMap<QString, std::function<void (const QString &, const QVariant &)> > > &keyboard = {}, + const KeyboardOnMessage &keyboard = {}, const QString &callBackQueryId = ""); /** @@ -230,6 +231,36 @@ public: bool sendFile( const QByteArray& file, const QString& fileName, const QVariant& chatId) override; + /** + * @brief sendPhoto This method will send image into chat with @a chatId + * @param photo this is photo path. + * @param chatId target chat + * @param replyToMessageId The unique identifier of the message to reply to, if any. + * @param keyboard A list of maps where each map represents a button with a callback function (optional). + * @return true if photo will snt successful + */ + bool sendPhoto(const QFileInfo& photo, + const QVariant& chatId, + const QString &description, + unsigned long long replyToMessageId = 0, + const KeyboardOnMessage &keyboard = {}); + + /** + * @brief sendPhoto This method will send image into chat with @a chatId + * @param photo this is photo data. + * @param chatId target chat + * @param fileName This is dispalyed name of photo. + * @param replyToMessageId The unique identifier of the message to reply to, if any. + * @param keyboard A list of maps where each map represents a button with a callback function (optional). + * @return true if photo will snt successful + */ + bool sendPhoto(const QByteArray& photo, + const QString& fileName, + const QVariant& chatId, + const QString &description, + unsigned long long replyToMessageId = 0, + const KeyboardOnMessage &keyboard = {}); + /** * @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 @@ -238,7 +269,7 @@ public: * @param description additional text for message. * @return true if the message sents successful else false. */ - bool sendFileWithDescription( const QByteArray& file, + bool sendFileWithDescription(const QByteArray& file, const QString& fileName, const QVariant& chatId, const QString& description); @@ -375,6 +406,10 @@ private slots: const QWeakPointer<iFile> &receiver); private: + + + bool sendFileWithPrivate(const QSharedPointer<TelegramSendFile>& file); + QString findFileInlocatStorage(const QString& fileId) const; QMap<QString, QSharedPointer<QJsonObject>> prepareInlineKeyBoard(const QList<QMap<QString, std::function<void (const QString &, const QVariant &)> > > &keyboard);