10#include "qstandardpaths.h"
12#include <QNetworkReply>
18 _manager =
new QNetworkAccessManager();
19 _manager->setAutoDeleteReplies(
true);
20 _requestExecutor =
new QTimer(
this);
21 _requestExecutor->setInterval(1000 / 20);
23 connect(_requestExecutor, &QTimer::timeout,
this , &IBot::handleEcxecuteRequest);
40 _startTime = QDateTime::currentDateTime();
45 if (!message->isValid())
48 auto id = message->updateId();
50 if (!_processed.contains(
id)) {
52 _processed.insert(
id);
53 _notProcessedUpdates[id] = message;
59QNetworkReply* IBot::sendRquestImpl(
const QSharedPointer<iRequest> &rquest) {
65#ifdef QTBOT_PRINT_RQUESTS
69 QNetworkReply* networkReplay =
nullptr;
71 switch (rquest->method()) {
73 networkReplay = _manager->get(QNetworkRequest(url));
84 QNetworkRequest netRequest(url);
86 auto httpData = rquest->argsToMultipartFormData();
88 networkReplay = _manager->post(netRequest, httpData.data());
89 connect(networkReplay, &QNetworkReply::destroyed, [httpData](){});
106 return _totalRequest;
110 return _parallelActiveNetworkThreads;
114 _parallelActiveNetworkThreads = newParallelActiveNetworkThreads;
117void IBot::setCurrentParallelActiveNetworkThreads(
int newParallelActiveNetworkThreads) {
118 _currentParallelActiveNetworkThreads = newParallelActiveNetworkThreads;
122 return _requestExecutor->interval() * 1000;
126 _requestExecutor->setInterval(1000 / newReqestLimitPerSecond);
131 auto&& responce = QSharedPointer<QPromise<QByteArray>>::create();
135 _requestQueue.insert(makeKey(rquest->priority()),
138 if (!_requestExecutor->isActive()) {
139 handleEcxecuteRequest();
140 _requestExecutor->start();
144 return responce->future();
149 const QString &pathToResult) {
150 auto&& responce = QSharedPointer<QPromise<QByteArray>>::create();
153 _requestQueue.insert(makeKey(rquest->priority()),
156 if (!_requestExecutor->isActive()) {
157 handleEcxecuteRequest();
158 _requestExecutor->start();
162 return responce->future();
167 _notProcessedUpdates.remove(message->updateId());
175 _processed.remove(messageID);
179 return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
186void IBot::handleEcxecuteRequest() {
187 if (!_requestQueue.size()) {
188 _requestExecutor->stop();
192 if (_currentParallelActiveNetworkThreads > _parallelActiveNetworkThreads) {
196 auto&& requestData = _requestQueue.take(_requestQueue.firstKey());
198 if (requestData.responceFilePath.size()) {
199 sendRequestPrivate(requestData.request, requestData.responceFilePath, requestData.responce);
203 sendRequestPrivate(requestData.request, requestData.responce);
207 unsigned long long key = _totalRequest;
213void IBot::sendRequestPrivate(
const QSharedPointer<iRequest> &rquest,
214 const QSharedPointer<QPromise<QByteArray> > &promise) {
216 QNetworkReply* networkReplay = sendRquestImpl(rquest);
217 if (!networkReplay) {
221 setCurrentParallelActiveNetworkThreads(_currentParallelActiveNetworkThreads + 1);
223 connect(networkReplay, &QNetworkReply::finished, [
this, networkReplay, promise](){
224 if (networkReplay->error() == QNetworkReply::NoError) {
225 promise->addResult(networkReplay->readAll());
229 QByteArray msg = networkReplay->errorString().toLatin1() + networkReplay->readAll();
230 promise->setException(HttpException(networkReplay->error(), msg));
231#ifdef QTBOT_PRINT_ERRORS
237 setCurrentParallelActiveNetworkThreads(_currentParallelActiveNetworkThreads - 1);
241 auto && setProggress = [promise](qint64 bytesCurrent, qint64 bytesTotal){
243 if (promise->future().progressMaximum() != bytesTotal)
244 promise->setProgressRange(0, bytesTotal);
246 promise->setProgressValue(bytesCurrent);
249 connect(networkReplay, &QNetworkReply::downloadProgress, setProggress);
250 connect(networkReplay, &QNetworkReply::uploadProgress, setProggress);
253void IBot::sendRequestPrivate(
const QSharedPointer<iRequest> &rquest,
254 const QString &pathToResult,
255 const QSharedPointer<QPromise<QByteArray>> & promise) {
256 auto&& file = QSharedPointer<QFile>::create(pathToResult);
258 if (!file->open(QIODeviceBase::WriteOnly | QIODevice::Truncate)) {
259 qCritical() <<
"Fail to wrote data into " << pathToResult;
263 QNetworkReply* networkReplay = sendRquestImpl(rquest);
264 if (!networkReplay) {
268 setCurrentParallelActiveNetworkThreads(_currentParallelActiveNetworkThreads + 1);
269 connect(networkReplay, &QNetworkReply::finished, [
this, promise, networkReplay, pathToResult](){
271 if (networkReplay->error() == QNetworkReply::NoError) {
272 QByteArray msg = networkReplay->errorString().toLatin1();
273 promise->setException(HttpException(networkReplay->error(), msg));
274#ifdef QTBOT_PRINT_ERRORS
278 promise->addResult(pathToResult.toUtf8());
281 setCurrentParallelActiveNetworkThreads(_currentParallelActiveNetworkThreads - 1);
284 connect(networkReplay, &QNetworkReply::readyRead, [networkReplay, promise, pathToResult, file](){
285 if (networkReplay->error() == QNetworkReply::NoError) {
286 file->write(networkReplay->readAll());
291 auto && setProggress = [promise](qint64 bytesCurrent, qint64 bytesTotal){
293 if (promise->future().progressMaximum() != bytesTotal)
294 promise->setProgressRange(0, bytesTotal);
296 promise->setProgressValue(bytesCurrent);
299 connect(networkReplay, &QNetworkReply::downloadProgress, setProggress);
300 connect(networkReplay, &QNetworkReply::uploadProgress, setProggress);
309 _processed = newProcessed;
321 if (_notProcessedUpdates.size()) {
322 auto toRemove = std::move(*_notProcessedUpdates.begin());
323 _notProcessedUpdates.erase(_notProcessedUpdates.cbegin());
virtual QString makeUrl(const QSharedPointer< iRequest > &request) const =0
makeUrl This method prepare a prefix url for http requests.
void setName(const QString &newName)
setName This method sets new value for the IBot::name field.
const QString & name() const
name This is name of the bot. usualy it fields will be received from the server after autication.
unsigned long long totalSentRequests() const
totalSentRequests This is total prepared requests count of bot from the start.
void markUpdateAsUnprocessed(const QSharedPointer< iUpdate > &message)
markMessageAsUnprocessed This method add the message into a not processed messages store.
void markUpdateAsProcessed(const QSharedPointer< iUpdate > &message)
markMessageAsProcessed This method remove message from the not processed messages store.
const QByteArray & token() const
token This is token value for authication on the remote server (bot)
int parallelActiveNetworkThreads() const
parallelActiveNetworkThreads
virtual void handleIncomeNewUpdate(const QSharedPointer< iUpdate > &)
handleIncomeNewUpdate This method just emit the sigReceiveUpdate signal.
int reqestLimitPerSecond() const
reqestLimitPerSecond this is request performence limitation. by default is 20 requests per second
void setReqestLimitPerSecond(int newReqestLimitPerSecond)
setReqestLimitPerSecond this method sets new limitation of bot performance.
virtual QString defaultFileStorageLocation() const
defaultFileStorageLocation This method return default file storage location.
void incomeNewUpdate(const QSharedPointer< iUpdate > &message)
incomeNewUpdate This method save incomed messages into store.
void setParallelActiveNetworkThreads(int newParallelActiveNetworkThreads)
setParallelActiveNetworkThreads
QSet< unsigned long long > processed() const
processed This method return list of processed mesages.
QFuture< QByteArray > sendRequest(const QSharedPointer< iRequest > &rquest)
sendRequest This method sent custom requests to the server.
virtual void setProcessed(const QSet< unsigned long long > &newProcessed)
setProcessed This method sets new list of processed mesages.
void setToken(const QByteArray &newToken)
setToken This is setter of the IBot::token value.
virtual void logout()
login This method remove login token of bot.
void sigReceiveUpdate(const QSharedPointer< iUpdate > &)
sigReceiveUpdate emit when but receive any updates from users.
QDateTime startTime() const
startTime this is time when bol wil started.
QSharedPointer< iUpdate > takeNextUnreadUpdate()
takeNextUnreadUpdate This method take a unread update and mark them as read.
@ Post
general post request
@ Upload
this is post request to upload a big data to telegram
@ Get
general ger request, all request data sent as a url line
RequestPriority
The RequestPriority enum.
The RequestData class is simple wrapper of request object with path of responce. If Path of responce ...