File indexing completed on 2024-05-12 04:45:55

0001 #include "nextnote.h"
0002 #include <QUrl>
0003 //#include <QDomDocument>
0004 #include <QJsonDocument>
0005 #include <QJsonObject>
0006 #include <QVariantMap>
0007 #include <QNetworkReply>
0008 
0009 const QString NextNote::API = QStringLiteral("/index.php/apps/notes/api/v0.2/");
0010 
0011 static const inline QNetworkRequest formRequest(const QUrl &url, const QString &user, const QString &password)
0012 {
0013     if (!url.isValid() && !user.isEmpty() && !password.isEmpty())
0014         return QNetworkRequest();
0015 
0016     const QString concatenated = user + ":" + password;
0017     const QByteArray data = concatenated.toLocal8Bit().toBase64();
0018     const QString headerData = "Basic " + data;
0019 
0020     //    QVariantMap headers
0021     //    {
0022     //        {"Authorization", headerData.toLocal8Bit()},
0023     //        {QString::number(QNetworkRequest::ContentTypeHeader),"application/json"}
0024     //    };
0025 
0026     QNetworkRequest request;
0027     request.setUrl(QUrl(url));
0028     request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
0029     request.setRawHeader(QString("Authorization").toLocal8Bit(), headerData.toLocal8Bit());
0030 
0031     return request;
0032 }
0033 
0034 NextNote::NextNote(QObject *parent)
0035     : AbstractNotesProvider(parent)
0036 {
0037 }
0038 
0039 NextNote::~NextNote()
0040 {
0041 }
0042 
0043 void NextNote::getNote(const QString &id)
0044 {
0045     QUrl relativeUrl("../.." + NextNote::API + QString("notes/%1").arg(id));
0046     auto url = QUrl(this->m_provider).resolved(relativeUrl);
0047     qDebug() << "THE RESOLVED URL IS" << url << this->m_provider;
0048 
0049 //    const auto request = formRequest(url, this->m_user, this->m_password);
0050     QString concatenated = this->m_user + ":" + this->m_password;
0051     QByteArray data = concatenated.toLocal8Bit().toBase64();
0052     QString headerData = "Basic " + data;
0053 
0054     QMap<QString, QString> header{{"Authorization", headerData.toLocal8Bit()}};
0055 
0056     auto downloader = new FMH::Downloader;
0057     connect(downloader, &FMH::Downloader::dataReady, [=](QByteArray array) {
0058         const auto notes = this->parseNotes(array);
0059         Q_EMIT this->noteReady(notes.isEmpty() ? FMH::MODEL() : notes.first());
0060         downloader->deleteLater();
0061     });
0062 
0063     downloader->getArray(url, header);
0064 }
0065 
0066 void NextNote::getBooklet(const QString &id)
0067 {
0068     Q_UNUSED(id)
0069 }
0070 
0071 void NextNote::sendNotes(QByteArray array)
0072 {
0073     Q_UNUSED(array)
0074     //    Q_EMIT this->notesReady(notes);
0075 }
0076 
0077 void NextNote::getNotes()
0078 {
0079     QUrl relativeUrl("../.." + NextNote::API + QString("notes"));
0080     auto url = QUrl(this->m_provider).resolved(relativeUrl);
0081     qDebug() << "THE RESOLVED URL IS" << url << this->m_provider;
0082 
0083     QString concatenated = this->m_user + ":" + this->m_password;
0084     QByteArray data = concatenated.toLocal8Bit().toBase64();
0085     QString headerData = "Basic " + data;
0086 
0087     QMap<QString, QString> header{{"Authorization", headerData.toLocal8Bit()}};
0088 
0089     const auto downloader = new FMH::Downloader;
0090     connect(downloader, &FMH::Downloader::dataReady, [=](QByteArray array) {
0091         // exclude notes that have its own category
0092         FMH::MODEL_LIST notes;
0093         for (const auto &data : this->parseNotes(array)) {
0094             auto item = data;
0095             item[FMH::MODEL_KEY::STAMP] = item[FMH::MODEL_KEY::ID];
0096             item[FMH::MODEL_KEY::USER] = this->user();
0097             item[FMH::MODEL_KEY::SERVER] = this->provider();
0098             item[FMH::MODEL_KEY::FORMAT] = ".txt";
0099 
0100             if (item[FMH::MODEL_KEY::CATEGORY].isEmpty() || item[FMH::MODEL_KEY::CATEGORY].isNull())
0101                 notes << item;
0102         }
0103 
0104         Q_EMIT this->notesReady(notes);
0105         downloader->deleteLater();
0106     });
0107 
0108     downloader->getArray(url, header);
0109 }
0110 
0111 void NextNote::getBooklets()
0112 {
0113     QUrl relativeUrl("../.." + NextNote::API + QString("notes"));
0114     auto url = QUrl(this->m_provider).resolved(relativeUrl);
0115     qDebug() << "THE RESOLVED URL IS" << url << this->m_provider;
0116 
0117     QString concatenated = this->m_user + ":" + this->m_password;
0118     QByteArray data = concatenated.toLocal8Bit().toBase64();
0119     QString headerData = "Basic " + data;
0120 
0121     QMap<QString, QString> header{{"Authorization", headerData.toLocal8Bit()}};
0122 
0123     const auto downloader = new FMH::Downloader;
0124     connect(downloader, &FMH::Downloader::dataReady, [=](QByteArray array) {
0125         // exclude notes that do not have their own category
0126         FMH::MODEL_LIST booklets;
0127         for (const auto &data : this->parseNotes(array)) {
0128             auto item = data;
0129             item[FMH::MODEL_KEY::STAMP] = item[FMH::MODEL_KEY::ID];
0130             item[FMH::MODEL_KEY::USER] = this->user();
0131             item[FMH::MODEL_KEY::SERVER] = this->provider();
0132             item[FMH::MODEL_KEY::FORMAT] = ".txt";
0133 
0134             if (!item[FMH::MODEL_KEY::CATEGORY].isEmpty() && !item[FMH::MODEL_KEY::CATEGORY].isNull())
0135                 booklets << item;
0136         }
0137 
0138         Q_EMIT this->bookletsReady(booklets);
0139         downloader->deleteLater();
0140     });
0141 
0142     downloader->getArray(url, header);
0143 }
0144 
0145 void NextNote::insertNote(const FMH::MODEL &note)
0146 {
0147     QByteArray payload = QJsonDocument::fromVariant(FMH::toMap(FMH::filterModel(note, {FMH::MODEL_KEY::CONTENT, FMH::MODEL_KEY::FAVORITE}))).toJson();
0148     qDebug() << "UPLOADING NEW NOT" << QVariant(payload).toString();
0149 
0150     QUrl relativeUrl("../.." + NextNote::API + QString("notes"));
0151     auto url = QUrl(this->m_provider).resolved(relativeUrl);
0152     qDebug() << "THE RESOLVED URL IS" << url << this->m_provider;
0153 
0154     const auto request = formRequest(url, this->m_user, this->m_password);
0155 
0156     auto restclient = new QNetworkAccessManager; // constructor
0157     QNetworkReply *reply = restclient->post(request, payload);
0158     connect(reply, &QNetworkReply::finished, [=, __note = note]() {
0159         qDebug() << "Note insertyion finished?";
0160         const auto notes = this->parseNotes(reply->readAll());
0161         Q_EMIT this->noteInserted([&]() -> FMH::MODEL {
0162             FMH::MODEL note;
0163             if (!notes.isEmpty()) {
0164                 note = notes.first();
0165                 note[FMH::MODEL_KEY::STAMP] = note[FMH::MODEL_KEY::ID]; // adds the id of the uploaded note as a stamp
0166                 note[FMH::MODEL_KEY::ID] = __note[FMH::MODEL_KEY::ID]; // adds the url of the original local note
0167                 note[FMH::MODEL_KEY::SERVER] = this->m_provider; // adds the provider server address
0168                 note[FMH::MODEL_KEY::USER] = this->m_user; // adds the user name
0169             }
0170             return note;
0171         }());
0172 
0173         reply->deleteLater();
0174         restclient->deleteLater();
0175     });
0176 }
0177 
0178 void NextNote::insertBooklet(const FMH::MODEL &booklet)
0179 {
0180     QByteArray payload = QJsonDocument::fromVariant(FMH::toMap(FMH::filterModel(booklet, {FMH::MODEL_KEY::CONTENT, FMH::MODEL_KEY::FAVORITE, FMH::MODEL_KEY::CATEGORY}))).toJson();
0181     qDebug() << "UPLOADING NEW BOOKLET" << QVariant(payload).toString();
0182 
0183     QUrl relativeUrl("../.." + NextNote::API + QString("notes"));
0184     auto url = QUrl(this->m_provider).resolved(relativeUrl);
0185     qDebug() << "THE RESOLVED URL IS" << url << this->m_provider;
0186 
0187     const auto request = formRequest(url, this->m_user, this->m_password);
0188 
0189     auto restclient = new QNetworkAccessManager; // constructor
0190     QNetworkReply *reply = restclient->post(request, payload);
0191     connect(reply, &QNetworkReply::finished, [=, __booklet = booklet]() {
0192         qDebug() << "Note insertyion finished?";
0193         const auto booklets = this->parseNotes(reply->readAll());
0194         Q_EMIT this->bookletInserted([&]() -> FMH::MODEL {
0195             FMH::MODEL p_booklet;
0196             if (!booklets.isEmpty()) {
0197                 p_booklet = booklets.first();
0198                 p_booklet[FMH::MODEL_KEY::STAMP] = p_booklet[FMH::MODEL_KEY::ID]; // adds the id of the local note as a stamp
0199                 p_booklet[FMH::MODEL_KEY::ID] = __booklet[FMH::MODEL_KEY::ID]; // adds the id of the local note as a stamp
0200                 p_booklet[FMH::MODEL_KEY::SERVER] = this->m_provider; // adds the provider server address
0201                 p_booklet[FMH::MODEL_KEY::USER] = this->m_user; // adds the user name
0202             }
0203             return p_booklet;
0204         }());
0205 
0206         restclient->deleteLater();
0207         reply->deleteLater();
0208     });
0209 }
0210 
0211 void NextNote::updateNote(const QString &id, const FMH::MODEL &note)
0212 {
0213     if (id.isEmpty() || note.isEmpty()) {
0214         qWarning() << "The id or note are empty. Can not proceed. NextNote::update";
0215         return;
0216     }
0217 
0218     QByteArray payload = QJsonDocument::fromVariant(FMH::toMap(FMH::filterModel(note, {FMH::MODEL_KEY::CONTENT, FMH::MODEL_KEY::FAVORITE, FMH::MODEL_KEY::MODIFIED, FMH::MODEL_KEY::CATEGORY}))).toJson();
0219     qDebug() << "UPDATING NOTE" << QVariant(payload).toString();
0220 
0221     QUrl relativeUrl("../.." + NextNote::API + QString("notes/%1").arg(id));
0222     auto url = QUrl(this->m_provider).resolved(relativeUrl);
0223     qDebug() << "THE RESOLVED URL IS" << url << this->m_provider;
0224 
0225     qDebug() << "tryiong to update note" << url;
0226     const auto request = formRequest(url, this->m_user, this->m_password);
0227 
0228     auto restclient = new QNetworkAccessManager; // constructor
0229     QNetworkReply *reply = restclient->put(request, payload);
0230     connect(reply, &QNetworkReply::finished, [=, __note = note]() {
0231         qDebug() << "Note update finished?" << reply->errorString();
0232         const auto notes = this->parseNotes(reply->readAll());
0233         Q_EMIT this->noteUpdated([&]() -> FMH::MODEL {
0234             FMH::MODEL note;
0235             if (notes.isEmpty())
0236                 return note;
0237 
0238             note = notes.first();
0239             note[FMH::MODEL_KEY::STAMP] = note[FMH::MODEL_KEY::ID]; // adds the id of the local note as a stamp
0240             note[FMH::MODEL_KEY::ID] = __note[FMH::MODEL_KEY::ID]; // adds the id of the local note as a stamp
0241             note[FMH::MODEL_KEY::SERVER] = this->m_provider; // adds the provider server address
0242             note[FMH::MODEL_KEY::USER] = this->m_user; // adds the user name
0243 
0244             return note;
0245         }());
0246 
0247         restclient->deleteLater();
0248         reply->deleteLater();
0249     });
0250 }
0251 
0252 void NextNote::updateBooklet(const QString &id, const FMH::MODEL &booklet)
0253 {
0254     if (id.isEmpty() || booklet.isEmpty()) {
0255         qWarning() << "The id or note are empty. Can not proceed. NextNote::update";
0256         return;
0257     }
0258 
0259     QByteArray payload = QJsonDocument::fromVariant(FMH::toMap(FMH::filterModel(booklet, {FMH::MODEL_KEY::CONTENT, FMH::MODEL_KEY::CATEGORY}))).toJson();
0260     qDebug() << "UPDATING BOOKLET" << QVariant(payload).toString();
0261 
0262     QUrl relativeUrl("../.." + NextNote::API + QString("notes/%1").arg(id));
0263     auto url = QUrl(this->m_provider).resolved(relativeUrl);
0264     qDebug() << "THE RESOLVED URL IS" << url << this->m_provider;
0265 
0266     qDebug() << "tryiong to update note" << url;
0267     const auto request = formRequest(url, this->m_user, this->m_password);
0268 
0269     auto restclient = new QNetworkAccessManager; // constructor
0270     QNetworkReply *reply = restclient->put(request, payload);
0271     connect(reply, &QNetworkReply::finished, [=, __booklet = booklet]() {
0272         qDebug() << "Note update finished?" << reply->errorString();
0273         const auto booklets = this->parseNotes(reply->readAll());
0274         Q_EMIT this->bookletUpdated([&]() -> FMH::MODEL {
0275             FMH::MODEL booklet;
0276 
0277             if (booklets.isEmpty())
0278                 return booklet;
0279 
0280             booklet = booklets.first();
0281             booklet[FMH::MODEL_KEY::STAMP] = booklet[FMH::MODEL_KEY::ID]; // adds the stamp to the local note form the remote id
0282             booklet[FMH::MODEL_KEY::ID] = __booklet[FMH::MODEL_KEY::ID]; // adds back the id of the local booklet
0283             booklet[FMH::MODEL_KEY::SERVER] = this->m_provider; // adds the provider server address
0284             booklet[FMH::MODEL_KEY::USER] = this->m_user; // adds the user name
0285 
0286             return booklet;
0287         }());
0288 
0289         restclient->deleteLater();
0290         reply->deleteLater();
0291     });
0292 }
0293 
0294 void NextNote::removeNote(const QString &id)
0295 {
0296     if (id.isEmpty()) {
0297         qWarning() << "The id is empty. Can not proceed. NextNote::remove";
0298         return;
0299     }
0300 
0301     QUrl relativeUrl("../.." + NextNote::API + QString("notes/%1").arg(id));
0302     auto url = QUrl(this->m_provider).resolved(relativeUrl);
0303     qDebug() << "THE RESOLVED URL IS" << url << this->m_provider;
0304 
0305     const auto request = formRequest(url, this->m_user, this->m_password);
0306     qDebug() << "trying to remove nextnote <<" << url;
0307     auto restclient = new QNetworkAccessManager; // constructor
0308     QNetworkReply *reply = restclient->deleteResource(request);
0309     connect(reply, &QNetworkReply::finished, [=]() {
0310         qDebug() << "Note remove finished?" << reply->errorString();
0311         Q_EMIT this->noteRemoved();
0312         restclient->deleteLater();
0313         reply->deleteLater();
0314     });
0315 }
0316 
0317 void NextNote::removeBooklet(const QString &id)
0318 {
0319     this->removeNote(id);
0320 }
0321 
0322 const FMH::MODEL_LIST NextNote::parseNotes(const QByteArray &array)
0323 {
0324     FMH::MODEL_LIST res;
0325     //  qDebug()<< "trying to parse notes" << array;
0326     QJsonParseError jsonParseError;
0327     QJsonDocument jsonResponse = QJsonDocument::fromJson(static_cast<QString>(array).toUtf8(), &jsonParseError);
0328 
0329     if (jsonParseError.error != QJsonParseError::NoError) {
0330         qDebug() << "ERROR PARSING" << array;
0331         return res;
0332     }
0333 
0334     const auto data = jsonResponse.toVariant();
0335 
0336     if (data.isNull() || !data.isValid())
0337         return res;
0338 
0339     if (!data.toList().isEmpty())
0340         res << FMH::toModelList(data.toList());
0341     else
0342         res << FMH::toModel(data.toMap());
0343 
0344     return res;
0345 }