remove all call back functions

This commit is contained in:
Andrei Yankovich 2023-09-24 23:28:27 +02:00
parent f96a9a81d8
commit d7c2923763
15 changed files with 231 additions and 226 deletions

View File

@ -21,7 +21,7 @@
],
"extraLib": "crypto",
"targetDir": "/media/D/builds/qTbot/Distro",
"deployVersion": "0.23.f1c28f6",
"deployVersion": "0.24.f96a9a8",
}

View File

@ -10,7 +10,7 @@
#include <QtCore/qglobal.h>
#define QTBOT_VERSION "0.23.f1c28f6"
#define QTBOT_VERSION "0.24.f96a9a8"
#if defined(QTBOT_LIBRARY)
# define QTBOT_EXPORT Q_DECL_EXPORT

View File

@ -10,9 +10,13 @@
namespace qTbot {
IBot::IBot()
{
IBot::IBot() {
_manager = new QNetworkAccessManager();
_manager->setAutoDeleteReplies(false);
}
IBot::~IBot() {
delete _manager;
}
const QByteArray &IBot::token() const {
@ -38,6 +42,33 @@ void IBot::incomeNewMessage(const QSharedPointer<iMessage> &message) {
}
}
QSharedPointer<QNetworkReply> IBot::sendRequest(const QSharedPointer<iRequest> &rquest) {
if (!rquest)
return nullptr;
auto&& getInfoRquest = makePrefix() + rquest->makeUpload();
auto&& networkReplay = QSharedPointer<QNetworkReply>(
_manager->get(QNetworkRequest(QUrl::fromEncoded(getInfoRquest))));
size_t address = reinterpret_cast<size_t>(networkReplay.get());
_replayStorage[address] = networkReplay;
connect(networkReplay.get(), &QNetworkReply::finished, this,
[this, address](){
_replayStorage.remove(address);
});
connect(networkReplay.get(), &QNetworkReply::errorOccurred, this,
[this, address](QNetworkReply::NetworkError err){
qWarning() << "The reqeust " << address << " finished with error code : " << err;
_replayStorage.remove(address);
});
return networkReplay;
}
void IBot::markMessageAsProcessed(const QSharedPointer<iMessage> &message) {
_notProcessedMessages.remove(message->messageId());
}

View File

@ -35,15 +35,7 @@ class QTBOT_EXPORT IBot: public QObject
Q_OBJECT
public:
IBot();
/**
* @brief Responce - This is labda for server responces.
* The first argument of a call back function is is request that was sent, second is server responce.
* And error code - 0 if request finished successfull
*/
using Responce = std::function<void(const QSharedPointer<iRequest>& request,
const QSharedPointer<iMessage>& responce,
unsigned int err)>;
~IBot();
/**
* @brief login This method get bae information of the bot from remote server.
@ -114,35 +106,32 @@ protected:
/**
* @brief makeMesasge This is factory method tha can create a messages types.
* @param data This is a raw data of the ansver.
* @param args This is list of arguments of the message.
* @return message object.
*/
template<class MessageType, class ... Args>
static QSharedPointer<MessageType> makeMesasge(Args&& ...args) {
return QSharedPointer<MessageType>(new MessageType(std::forward<Args>(args)...));
static QSharedPointer<MessageType> makeMesasge(const QByteArray& data, Args&& ...args) {
auto&& ptr = QSharedPointer<MessageType>(new MessageType(std::forward<Args>(args)...));
ptr->setRawData(data);
return ptr;
}
/**
* @brief makePrefix This method prepare a prefix url for http requests.
* @brief makeUrl This method prepare a prefix url for http requests.
* @param request - This is request object for that will be prepared url.
* @return http request prefix
*/
virtual QByteArray makePrefix() const = 0;
virtual QByteArray makeUrl(const QSharedPointer<iRequest>& request) const = 0;
/**
* @brief sendRequest This method sent custom requests to the server.
* @param rquest This is message that will be sent to server.
* @param cb This is call back function for the responce.
* @return id of request if the request will sent successful else 0.
* @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.
*/
virtual size_t sendRequest(const QSharedPointer<iRequest>& rquest, const Responce& cb) = 0;
/**
* @brief sendRequest This method sent custom requests to the server.
* @param rquest This is message that will be sent to server.
* @param cb This is call back function for the responce.
* @return true if the request will sent successful else false.
*/
virtual QSharedPointer<QNetworkReply> sendRequest(const QSharedPointer<iRequest>& rquest) = 0;
QSharedPointer<QNetworkReply> sendRequest(const QSharedPointer<iRequest>& rquest);
/**
* @brief setToken This is setter of the IBot::token value.
@ -188,13 +177,13 @@ signals:
private:
QByteArray _token;
QString _name;
QMap<unsigned long long, QSharedPointer<iMessage>> _notProcessedMessages;
QSet<unsigned long long> _processed;
QNetworkAccessManager *_manager = nullptr;
QMap<size_t,QSharedPointer<QNetworkReply>> _replayStorage;
};
}

View File

@ -27,6 +27,12 @@ public:
* @return data array prepared to sending.
*/
virtual QByteArray makeUpload() const = 0;
/**
* @brief baseAddress This method return base domain of remote server.
* @return base domain name of remoute server.
*/
virtual QByteArray baseAddress() const = 0;
};
}

View File

@ -8,7 +8,10 @@
#include "itelegrambot.h"
#include "qTbot/messages/telegrammsg.h"
#include "qTbot/messages/telegramupdateanswer.h"
#include "file.h"
#include "qTbot/requests/telegrammdownloadfile.h"
#include "qdir.h"
#include "virtualfile.h"
#include <QNetworkAccessManager>
#include <qTbot/requests/telegramgetfile.h>
@ -24,12 +27,9 @@
namespace qTbot {
ITelegramBot::ITelegramBot() {
_manager = new QNetworkAccessManager();
_manager->setAutoDeleteReplies(false);
}
ITelegramBot::~ITelegramBot() {
delete _manager;
}
bool ITelegramBot::login(const QByteArray &token) {
@ -39,22 +39,18 @@ bool ITelegramBot::login(const QByteArray &token) {
setToken(token);
ITelegramBot::Responce cb = [this]( const QSharedPointer<iRequest>& ,
const QSharedPointer<iMessage>& responce,
int err) {
if (err) {
qDebug() << "Network error occured. code: " << err;
}
if (auto message = responce.dynamicCast<ITelegramMessage>()) {
setId(message->rawJson().value("id").toInt());
setName(message->rawJson().value("first_name").toString());
setUsername(message->rawJson().value("username").toString());
}
};
_loginReplay = sendRequest(QSharedPointer<TelegramGetMe>::create());
if (_loginReplay) {
connect(_loginReplay.get(), &QNetworkReply::finished,
this, &ITelegramBot::handleLogin,
Qt::DirectConnection);
connect(_loginReplay.get(), &QNetworkReply::errorOccurred,
this, &ITelegramBot::handleLoginErr,
Qt::DirectConnection);
return true;
}
return sendRequest(QSharedPointer<TelegramGetMe>::create(), cb);
return false;
}
bool ITelegramBot::sendMessage(const QVariant &chatId, const QString &text) {
@ -65,8 +61,7 @@ bool ITelegramBot::sendSpecificMessage(const QVariant & chatId,
const QString &text,
unsigned long long replyToMessageId,
bool markdown,
bool disableWebPagePreview,
const Responce &cb) {
bool disableWebPagePreview) {
if (!chatId.isValid() || chatId.isNull())
return false;
@ -80,7 +75,8 @@ bool ITelegramBot::sendSpecificMessage(const QVariant & chatId,
replyToMessageId,
markdown,
disableWebPagePreview);
return sendRequest(msg, cb);
return bool(sendRequest(msg));
}
QSharedPointer<iFile> ITelegramBot::getFile(const QString &fileId, iFile::Type fileType) {
@ -114,7 +110,16 @@ QSharedPointer<iFile> ITelegramBot::getFile(const QString &fileId, iFile::Type f
return result;
}
auto msg = QSharedPointer<TelegramGetFile>::create(fileId);
auto&& metaInfo = getFileInfoByUniqueId(fileId);
if (!metaInfo) {
// if (auto&& replay = getFileMeta(fileId)) {
// } else {
// return nullptr;
// };
}
auto msg = QSharedPointer<TelegrammDownloadFile>::create(metaInfo->path());
QDir().mkpath(defaultFileStorageLocation());
@ -135,115 +140,9 @@ QSharedPointer<iFile> ITelegramBot::getFile(const QString &fileId, iFile::Type f
return result;
}
bool ITelegramBot::getFile(const QString &fileId,
std::function<void (const QSharedPointer<File> &)> cb) {
if (auto&& ptr = getFile(fileId, iFile::Local)) {
if (ptr->finished() && cb) {
cb(ptr.dynamicCast<File>());
return true;
}
connect(ptr.data(), &iFile::finishedChanged, [cb, ptr](){
cb(ptr.dynamicCast<File>());
});
connect(ptr.data(), &iFile::errorChanged, [cb, ptr](){
cb(ptr.dynamicCast<File>());
});
return true;
}
return false;
}
bool ITelegramBot::getFile(const QString &fileId,
std::function<void (const QSharedPointer<VirtualFile> &)> cb) {
if (auto&& ptr = getFile(fileId, iFile::Local)) {
if (ptr->finished() && cb) {
cb(ptr.dynamicCast<VirtualFile>());
return true;
}
connect(ptr.data(), &iFile::finishedChanged, [cb, ptr](){
cb(ptr.dynamicCast<VirtualFile>());
});
connect(ptr.data(), &iFile::errorChanged, [cb, ptr](){
cb(ptr.dynamicCast<VirtualFile>());
});
return true;
}
return false;
}
QByteArray ITelegramBot::makePrefix() const {
return "https://api.telegram.org/bot" + token();
}
size_t ITelegramBot::sendRequest(const QSharedPointer<iRequest> &rquest, const Responce &cb) {
if (!rquest)
return 0;
auto getInfoRquest = makePrefix() + rquest->makeUpload();
auto networkReplay = QSharedPointer<QNetworkReply>(_manager->get(QNetworkRequest(QUrl::fromEncoded(getInfoRquest))));
if (!networkReplay)
return 0;
auto handler = [rquest, cb, networkReplay]() {
auto rawData = networkReplay->readAll();
qDebug() << rawData;
auto message = IBot::makeMesasge<TelegramUpdateAnswer>();
message->setRawData(rawData);
if (!message->isValid()) {
qDebug() << "Some request is wrong: code:" << message->rawJson().value("error_code").toInt();
qDebug() << "What: " << message->rawJson().value("description").toString();
return;
}
if (cb) {
cb(rquest, message, 0);
}
};
auto err = [rquest, cb, networkReplay](QNetworkReply::NetworkError err) {
networkReplay->deleteLater();
if (cb) {
cb(rquest, nullptr, err);
}
};
connect(networkReplay.get(), &QNetworkReply::finished, handler);
connect(networkReplay.get(), &QNetworkReply::errorOccurred, err);
return true;
}
QSharedPointer<QNetworkReply> ITelegramBot::sendRequest(const QSharedPointer<iRequest> &rquest) {
if (!rquest)
return 0;
auto getInfoRquest = makePrefix() + rquest->makeUpload();
qDebug() << getInfoRquest;
auto&& networkReplay = QSharedPointer<QNetworkReply>(_manager->get(QNetworkRequest(QUrl::fromEncoded(getInfoRquest))));
if (!networkReplay)
return 0;
return std::move(networkReplay);
QSharedPointer<QNetworkReply> ITelegramBot::getFileMeta(const QString &fileId) {
auto msg = QSharedPointer<TelegramGetFile>::create(fileId);
return sendRequest(msg);
}
int ITelegramBot::getFileSizeByUniqueId(const QString &id) const {
@ -254,10 +153,35 @@ int ITelegramBot::getFileSizeByUniqueId(const QString &id) const {
return 0;
}
void ITelegramBot::incomeNewMessage(const QSharedPointer<iMessage> &msg) {
IBot::incomeNewMessage(msg);
QSharedPointer<TelegramFile> ITelegramBot::getFileInfoByUniqueId(const QString &id) const {
return _filesMetaInfo.value(id, nullptr);
}
extractAllMetaInfoFromUpdate(msg);
void ITelegramBot::handleLogin() {
if (_loginReplay) {
auto&& ans = makeMesasge<TelegramUpdateAnswer>(_loginReplay->readAll());
if (!ans->isValid()) {
qWarning() << "login error occured: ";
}
auto&& result = ans->result().toObject();
setId(result.value("id").toInt());
setName( result.value("first_name").toString());
setUsername( result.value("username").toString());
_loginReplay.reset();
}
}
void ITelegramBot::handleLoginErr(QNetworkReply::NetworkError err) {
if (err) {
qDebug() << "Network error occured. code: " << err;
}
_loginReplay.reset();
}
QString ITelegramBot::findFileInlocatStorage(const QString &fileId) const {
@ -274,31 +198,14 @@ QString ITelegramBot::findFileInlocatStorage(const QString &fileId) const {
return "";
}
void ITelegramBot::extractAllMetaInfoFromUpdate(const QSharedPointer<iMessage> &answer) {
if (auto && tmessage = answer.dynamicCast<TelegramMsg>()) {
if (tmessage->contains(tmessage->Document)) {
auto &&doc = tmessage->documents();
_filesMetaInfo[doc->fileId()] = doc;
}
if (tmessage->contains(tmessage->Image)) {
auto &&imgs = tmessage->images();
for (const auto& img : qAsConst(imgs)) {
_filesMetaInfo[img->fileId()] = img;
}
}
if (tmessage->contains(tmessage->Audio)) {
auto &&audio = tmessage->image();
_filesMetaInfo[audio->fileId()] = audio;
}
}
}
void ITelegramBot::setUsername(const QString &newUsername) {
_username = newUsername;
}
QByteArray ITelegramBot::makeUrl(const QSharedPointer<iRequest> &request) const {
return request->baseAddress() + "/bot" + token() + request->makeUpload();
}
void ITelegramBot::setId(unsigned long long newId) {
_id = newId;
}

View File

@ -10,9 +10,7 @@
#ifndef ITELEGRAMBOT_H
#define ITELEGRAMBOT_H
#include "file.h"
#include "ibot.h"
#include "virtualfile.h"
#include <QObject>
class QNetworkAccessManager;
@ -55,8 +53,6 @@ public:
* 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.
* @param cb A callback function to handle the server response after sending the message. This parameter
* can be left empty if no callback is required.
*
* @return `true` if the message was successfully sent, and `false` otherwise.
*
@ -76,37 +72,18 @@ public:
const QString& text,
unsigned long long replyToMessageId = 0,
bool markdown = true,
bool disableWebPagePreview = false,
const Responce& cb = {});
bool disableWebPagePreview = false);
QSharedPointer<iFile> getFile(const QString& fileId, iFile::Type fileType = iFile::Type::Ram) override;
/**
* @brief Get a file by its ID.
*
* This function allows you to retrieve a file by its ID.
*
* @param fileId The ID of the file to retrieve.
* @param cb The callback function to be called after the file is retrieved.
* The function takes a shared_ptr to a File object as a parameter.
* @return Returns true if the file retrieval operation was successfully initiated and false in case of an error.
* @brief getFileMeta This method receive meta information of the file.
* @param fileId This is id of the file.
* @param cb result.
* @return true if the reqests sents successful.
*/
bool getFile(const QString& fileId, std::function<void(const QSharedPointer<File>&)> cb);
/**
* @brief Get a virtual file by its ID.
*
* This function allows you to retrieve a virtual file by its ID.
*
* @param fileId The ID of the virtual file to retrieve.
* @param cb The callback function to be called after the virtual file is retrieved.
* The function takes a shared_ptr to a VirtualFile object as a parameter.
* @return Returns true if the virtual file retrieval operation was successfully initiated and false in case of an error.
*/
bool getFile(const QString& fileId, std::function<void(const QSharedPointer<VirtualFile>&)> cb);
QSharedPointer<QNetworkReply> getFileMeta(const QString& fileId);
// to do
// * forwardMessage implementations
@ -176,14 +153,7 @@ protected:
*/
void setUsername(const QString &newUsername);
/**
* @brief makePrefix This method prepare a prefix message for all telegramm bots.
* @return telegramm request prefix/
*/
QByteArray makePrefix() const override;
size_t sendRequest(const QSharedPointer<iRequest>& rquest, const Responce& cb) override;
QSharedPointer<QNetworkReply> sendRequest(const QSharedPointer<iRequest>& rquest) override;
QByteArray makeUrl(const QSharedPointer<iRequest>& request) const override;
/**
* @brief getFileSizeByUniqueId This method return size of the file by id
@ -192,15 +162,24 @@ protected:
*/
int getFileSizeByUniqueId(const QString& id) const;
void incomeNewMessage(const QSharedPointer<iMessage>& msg) override;
/**
* @brief getFileInfoByUniqueId return a local saved meta information about the file.
* @param id This is id of the file.
* @return shared pointer to the meta information of the file. If information no exists return nullptr;
*/
QSharedPointer<TelegramFile> getFileInfoByUniqueId(const QString& id) const;
private slots:
void handleLogin();
void handleLoginErr(QNetworkReply::NetworkError err);
private:
QString findFileInlocatStorage(const QString& fileId) const;
void extractAllMetaInfoFromUpdate(const QSharedPointer<iMessage> &answer);
unsigned long long _id = 0;
QString _username;
QNetworkAccessManager *_manager = nullptr;
QSharedPointer<QNetworkReply> _loginReplay;
QHash<QString, QSharedPointer<TelegramFile>> _filesMetaInfo;

View File

@ -22,6 +22,15 @@ int TelegramFile::fileSize() const {
return rawJson()["file_size"].toInt();
}
QString TelegramFile::path() {
if (_used)
return "";
_used = true;
return rawJson()["file_path"].toString();
}
QString TelegramFile::fileId() const {
return rawJson()["file_id"].toString();
}

View File

@ -42,6 +42,16 @@ public:
* @return The file size of the photo.
*/
int fileSize() const;
/**
* @brief Returns the file path to get from web.
* @return The file size of the photo. return empty string if file alredy used.
* @note posible to get file from web only one time after invoke the getFile method. If you invoke this method 2 times on the second time you receive empty string. This is rooles of the telegram backend. see https://telegram-bot-sdk.readme.io/reference/getfile
*/
QString path();
private:
bool _used = false;
};
}
#endif // TELEGRAMFILE_H

View File

@ -18,6 +18,14 @@ QJsonValue TelegramUpdateAnswer::result() const {
return rawJson().value("result");
}
int TelegramUpdateAnswer::errorCode() const {
return rawJson().value("error_code").toInt();
}
QString TelegramUpdateAnswer::errorDescription() const {
return rawJson().value("description").toString();
}
QString TelegramUpdateAnswer::from() const {
return "";
}

View File

@ -30,6 +30,18 @@ public:
*/
QJsonValue result() const;
/**
* @brief errorCode This is error code (if exist)
* @return error code
*/
int errorCode() const;
/**
* @brief errorDescription This is text description : what is happend.
* @return text message about error.
*/
QString errorDescription() const;
QString from() const override;
QVariant chatId() const override;

View File

@ -0,0 +1,20 @@
//#
//# 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 "telegrammdownloadfile.h"
namespace qTbot {
TelegrammDownloadFile::TelegrammDownloadFile(const QByteArray &filePath):
TelegramSingleRquest(filePath, {}) {
}
QByteArray TelegrammDownloadFile::baseAddress() const {
return "https://api.telegram.org/file";
}
}

View File

@ -0,0 +1,29 @@
//#
//# 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 TELEGRAMMDOWNLOADFILE_H
#define TELEGRAMMDOWNLOADFILE_H
#include "telegramsinglerquest.h"
namespace qTbot {
/**
* @brief The TelegrammDownloadFile class prepare link to download telegramm files.
*/
class QTBOT_EXPORT TelegrammDownloadFile final: public TelegramSingleRquest
{
public:
TelegrammDownloadFile(const QByteArray &filePath);
QByteArray baseAddress() const override;
};
}
#endif // TELEGRAMMDOWNLOADFILE_H

View File

@ -46,6 +46,10 @@ QByteArray TelegramSingleRquest::makeUpload() const {
}
QByteArray TelegramSingleRquest::baseAddress() const {
return "https://api.telegram.org";
}
const QMap<QString, QVariant>& TelegramSingleRquest::args() const {
return _args;
}

View File

@ -50,6 +50,7 @@ public:
TelegramSingleRquest(const QByteArray& request);
QByteArray makeUpload() const override final;
QByteArray baseAddress() const override;
protected: