Skip to content
Snippets Groups Projects
updatehandler.cpp 5.75 KiB
Newer Older
#include "updatehandler.h"
akiraohgaki's avatar
akiraohgaki committed
#include <QStringList>
#include <QJsonValue>
#include <QJsonArray>
#include <QJsonObject>
#include <QDateTime>
akiraohgaki's avatar
akiraohgaki committed
#include <QThread>
#include <QDebug>
akiraohgaki's avatar
akiraohgaki committed

akiraohgaki's avatar
akiraohgaki committed
#ifdef QTLIB_UNIX
#include "appimage/update.h"
#endif

akiraohgaki's avatar
akiraohgaki committed
#include "qtlib_file.h"

akiraohgaki's avatar
akiraohgaki committed
#include "handlers/confighandler.h"

UpdateHandler::UpdateHandler(ConfigHandler *configHandler, QObject *parent)
akiraohgaki's avatar
akiraohgaki committed
    : QObject(parent), configHandler_(configHandler)
{}

akiraohgaki's avatar
akiraohgaki committed
void UpdateHandler::checkAll()
akiraohgaki's avatar
akiraohgaki committed
{
akiraohgaki's avatar
akiraohgaki committed
    emit checkAllStarted();

akiraohgaki's avatar
akiraohgaki committed
    // Resets data
akiraohgaki's avatar
akiraohgaki committed
    QJsonObject updateAvailableItems;
akiraohgaki's avatar
akiraohgaki committed
    configHandler_->setUsrConfigUpdateAvailableItems(updateAvailableItems);
akiraohgaki's avatar
akiraohgaki committed

akiraohgaki's avatar
akiraohgaki committed
    auto installedItems = configHandler_->getUsrConfigInstalledItems();

akiraohgaki's avatar
akiraohgaki committed
    if (installedItems.isEmpty()) {
        emit checkAllFinished();
        return;
akiraohgaki's avatar
akiraohgaki committed
    }

    for (const auto &itemKey : installedItems.keys()) {
        auto installedItem = installedItems[itemKey].toObject();
akiraohgaki's avatar
akiraohgaki committed
        auto filename = installedItem["filename"].toString();
akiraohgaki's avatar
akiraohgaki committed
        auto installType = installedItem["install_type"].toString();

akiraohgaki's avatar
akiraohgaki committed
        qtlib::File file;
akiraohgaki's avatar
akiraohgaki committed
#ifdef QTLIB_UNIX
akiraohgaki's avatar
akiraohgaki committed
        file.setPath(configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString() + "/" + filename);
akiraohgaki's avatar
akiraohgaki committed
#else
akiraohgaki's avatar
akiraohgaki committed
        file.setPath(configHandler_->getAppConfigInstallTypes()[installType].toObject()["generic_destination"].toString() + "/" + filename);
akiraohgaki's avatar
akiraohgaki committed
#endif

akiraohgaki's avatar
akiraohgaki committed
        QString updateMethod = "";
akiraohgaki's avatar
akiraohgaki committed

akiraohgaki's avatar
akiraohgaki committed
        if (installType == "bin") {
akiraohgaki's avatar
akiraohgaki committed
#ifdef QTLIB_UNIX
akiraohgaki's avatar
akiraohgaki committed
            if (file.path().endsWith(".appimage", Qt::CaseInsensitive)) {
                if (checkAppImage(file.path())) {
akiraohgaki's avatar
akiraohgaki committed
                    updateMethod = "appimageupdate";
akiraohgaki's avatar
akiraohgaki committed
                }
akiraohgaki's avatar
akiraohgaki committed
                //else if (checkAppImageWithOcsApi(itemKey)) {
                //    updateMethod = "appimageupdatewithocsapi";
                //}
akiraohgaki's avatar
akiraohgaki committed
            }
akiraohgaki's avatar
akiraohgaki committed
#endif
akiraohgaki's avatar
akiraohgaki committed
        }
akiraohgaki's avatar
akiraohgaki committed

        if (!updateMethod.isEmpty()) {
            QJsonObject updateAvailableItem;
            updateAvailableItem["installed_item"] = itemKey;
            updateAvailableItem["update_method"] = updateMethod;
            // Use installed item's key as unique key to the update available item
            configHandler_->setUsrConfigUpdateAvailableItemsItem(itemKey, updateAvailableItem);
        }
akiraohgaki's avatar
akiraohgaki committed
    }

akiraohgaki's avatar
akiraohgaki committed
    auto application = configHandler_->getUsrConfigApplication();
akiraohgaki's avatar
akiraohgaki committed
    application["update_checked_at"] = QDateTime::currentMSecsSinceEpoch();
    configHandler_->setUsrConfigApplication(application);

    emit checkAllFinished();
akiraohgaki's avatar
akiraohgaki committed
void UpdateHandler::update(const QString &itemKey)
akiraohgaki's avatar
akiraohgaki committed
    auto updateAvailableItems = configHandler_->getUsrConfigUpdateAvailableItems();

    if (!updateAvailableItems.contains(itemKey)) {
        return;
    }

    auto updateMethod = updateAvailableItems[itemKey].toObject()["update_method"].toString();
akiraohgaki's avatar
akiraohgaki committed

#ifdef QTLIB_UNIX
akiraohgaki's avatar
akiraohgaki committed
    if (updateMethod == "appimageupdate") {
        updateAppImage(itemKey);
akiraohgaki's avatar
akiraohgaki committed
    }
akiraohgaki's avatar
akiraohgaki committed
    //else if (updateMethod == "appimageupdatewithocsapi") {
    //    updateAppImageWithOcsApi(itemKey);
    //}
akiraohgaki's avatar
akiraohgaki committed
#endif
akiraohgaki's avatar
akiraohgaki committed

#ifdef QTLIB_UNIX
QString UpdateHandler::describeAppImage(const QString &path) const
{
akiraohgaki's avatar
akiraohgaki committed
    appimage::update::Updater appImageUpdater(path.toStdString());
    QString updateInformation;
akiraohgaki's avatar
akiraohgaki committed
    std::string description;
    if (appImageUpdater.describeAppImage(description)) {
        updateInformation = QString::fromStdString(description);
    }
    return updateInformation;
}

bool UpdateHandler::checkAppImage(const QString &path) const
akiraohgaki's avatar
akiraohgaki committed
{
    appimage::update::Updater appImageUpdater(path.toStdString());
    bool updateAvailable;
akiraohgaki's avatar
akiraohgaki committed
    if (appImageUpdater.checkForChanges(updateAvailable)) {
        return updateAvailable;
    }
akiraohgaki's avatar
akiraohgaki committed
    return false;
}

akiraohgaki's avatar
akiraohgaki committed
void UpdateHandler::updateAppImage(const QString &itemKey)
akiraohgaki's avatar
akiraohgaki committed
    auto updateAvailableItem = configHandler_->getUsrConfigUpdateAvailableItems()[itemKey].toObject();
    auto installedItemKey = updateAvailableItem["installed_item"].toString();
akiraohgaki's avatar
akiraohgaki committed
    auto installedItems = configHandler_->getUsrConfigInstalledItems();
akiraohgaki's avatar
akiraohgaki committed

    if (!installedItems.contains(installedItemKey)) {
        return;
    }

    auto installedItem = installedItems[installedItemKey].toObject();
    auto filename = installedItem["filename"].toString();
    auto installType = installedItem["install_type"].toString();
akiraohgaki's avatar
akiraohgaki committed

akiraohgaki's avatar
akiraohgaki committed
    qtlib::File file(configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString() + "/" + filename);
akiraohgaki's avatar
akiraohgaki committed

    auto newFilename = filename;
akiraohgaki's avatar
akiraohgaki committed
    auto updateInformation = describeAppImage(file.path());
akiraohgaki's avatar
akiraohgaki committed
    for (const auto &info : updateInformation.split("\n")) {
        if (info.endsWith(".zsync", Qt::CaseInsensitive)) {
akiraohgaki's avatar
akiraohgaki committed
            newFilename = info.split("|").last().split("/").last().replace(".zsync", "", Qt::CaseInsensitive);
akiraohgaki's avatar
akiraohgaki committed
            break;
        }
    }

akiraohgaki's avatar
akiraohgaki committed
    appimage::update::Updater appImageUpdater(file.path().toStdString(), false);
akiraohgaki's avatar
akiraohgaki committed

akiraohgaki's avatar
akiraohgaki committed
    if (!appImageUpdater.start()) {
        return;
    }
akiraohgaki's avatar
akiraohgaki committed

akiraohgaki's avatar
akiraohgaki committed
    emit updateStarted(itemKey);
akiraohgaki's avatar
akiraohgaki committed

akiraohgaki's avatar
akiraohgaki committed
    while (!appImageUpdater.isDone()) {
        QThread::msleep(100);
        double progress;
        if (appImageUpdater.progress(progress)) {
            emit updateProgress(itemKey, progress * 100);
        }
    }
akiraohgaki's avatar
akiraohgaki committed

akiraohgaki's avatar
akiraohgaki committed
    if (appImageUpdater.hasError()) {
        std::string nextMessage;
        while (appImageUpdater.nextStatusMessage(nextMessage)) {
            qWarning() << QString::fromStdString(nextMessage);
akiraohgaki's avatar
akiraohgaki committed
        }

akiraohgaki's avatar
akiraohgaki committed
        emit updateFinished(itemKey);
        return;
    }
akiraohgaki's avatar
akiraohgaki committed

akiraohgaki's avatar
akiraohgaki committed
    installedItem["filename"] = newFilename;
    QJsonArray files;
    files.append(QJsonValue(newFilename));
    installedItem["files"] = files;
    installedItem["installed_at"] = QDateTime::currentMSecsSinceEpoch();

    configHandler_->setUsrConfigInstalledItemsItem(installedItemKey, installedItem);
akiraohgaki's avatar
akiraohgaki committed

akiraohgaki's avatar
akiraohgaki committed
    if (newFilename != filename) {
        file.remove();
akiraohgaki's avatar
akiraohgaki committed
    }
akiraohgaki's avatar
akiraohgaki committed

    configHandler_->removeUsrConfigUpdateAvailableItemsItem(itemKey);

    emit updateFinished(itemKey);
akiraohgaki's avatar
akiraohgaki committed
}
#endif