Skip to content
Snippets Groups Projects
updatehandler.cpp 5.67 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include "updatehandler.h"
    
    akiraohgaki's avatar
    akiraohgaki committed
    #include <QStringList>
    #include <QJsonValue>
    #include <QJsonArray>
    #include <QJsonObject>
    #include <QDateTime>
    
    
    akiraohgaki's avatar
    akiraohgaki committed
    #ifdef QTLIB_UNIX
    
    akiraohgaki's avatar
    akiraohgaki committed
    #include <thread>
    #include <chrono>
    
    
    akiraohgaki's avatar
    akiraohgaki committed
    #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();
    
        auto application = configHandler_->getUsrConfigApplication();
        auto installedItems = configHandler_->getUsrConfigInstalledItems();
    
        if (installedItems.isEmpty()
                || (application.contains("update_checked_at")
                    && application["update_checked_at"].toInt() + (1000 * 60 * 60 * 24) > QDateTime::currentMSecsSinceEpoch())) {
            emit checkAllFinished();
            return;
        }
    
        // Clear data
        QJsonObject updateAvailable;
        configHandler_->setUsrConfigUpdateAvailable(updateAvailable);
    
        for (const auto &itemKey : installedItems.keys()) {
            auto installedItem = installedItems[itemKey].toObject();
            auto installType = installedItem["install_type"].toString();
    
            QString destDir = "";
    #ifdef QTLIB_UNIX
            destDir = configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString();
    #else
            destDir = configHandler_->getAppConfigInstallTypes()[installType].toObject()["generic_destination"].toString();
    #endif
    
            if (installType == "bin") {
                for (const auto &filenameValue : installedItem["files"].toArray()) {
                    auto filename = filenameValue.toString();
                    QString path = destDir + "/" + filename;
                    // Use file path as unique key for entry in update_available data
                    auto fileKey = path;
                    QJsonObject updateAvailableFile;
    
    #ifdef QTLIB_UNIX
                    if (filename.endsWith(".appimage", Qt::CaseInsensitive)) {
                        if (checkAppImage(path)) {
                            updateAvailableFile["path"] = path;
                            updateAvailableFile["filename"] = filename;
                            updateAvailableFile["installed_item"] = itemKey;
                            updateAvailableFile["update_method"] = QString("appimageupdate");
                            configHandler_->setUsrConfigUpdateAvailableFile(fileKey, updateAvailableFile);
                        }
                        //else if (checkAppImageWithOcsApi(itemKey, filename)) {}
                    }
    #endif
                }
            }
        }
    
        application["update_checked_at"] = QDateTime::currentMSecsSinceEpoch();
        configHandler_->setUsrConfigApplication(application);
    
        emit checkAllFinished();
    
    akiraohgaki's avatar
    akiraohgaki committed
    void UpdateHandler::update(const QString &fileKey)
    
    akiraohgaki's avatar
    akiraohgaki committed
        if (configHandler_->getUsrConfigUpdateAvailable().contains(fileKey)) {
            auto updateAvailableFile = configHandler_->getUsrConfigUpdateAvailable()[fileKey].toObject();
    
    #ifdef QTLIB_UNIX
            if (updateAvailableFile["update_method"].toString() == "appimageupdate") {
                updateAppImage(fileKey);
            }
    #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 &fileKey)
    
    akiraohgaki's avatar
    akiraohgaki committed
        auto updateAvailableFile = configHandler_->getUsrConfigUpdateAvailable()[fileKey].toObject();
    
        auto path = updateAvailableFile["path"].toString();
        auto filename = updateAvailableFile["filename"].toString();
        auto itemKey = updateAvailableFile["installed_item"].toString();
    
        auto newFilename = filename;
        auto updateInformation = describeAppImage(path);
        for (const auto &info : updateInformation.split("\n")) {
            if (info.endsWith(".zsync", Qt::CaseInsensitive)) {
                newFilename = info.replace(".zsync", "", Qt::CaseInsensitive).split("/").last();
                break;
            }
        }
    
    
    akiraohgaki's avatar
    akiraohgaki committed
        appimage::update::Updater appImageUpdater(path.toStdString(), false);
    
    akiraohgaki's avatar
    akiraohgaki committed
        if (appImageUpdater.start()) {
    
    akiraohgaki's avatar
    akiraohgaki committed
            emit updateStarted(fileKey);
    
    
    akiraohgaki's avatar
    akiraohgaki committed
            while (!appImageUpdater.isDone()) {
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
                double progress;
                if (appImageUpdater.progress(progress)) {
    
    akiraohgaki's avatar
    akiraohgaki committed
                    emit updateProgress(fileKey, progress * 100);
    
    akiraohgaki's avatar
    akiraohgaki committed
                }
            }
    
    akiraohgaki's avatar
    akiraohgaki committed
    
    
    akiraohgaki's avatar
    akiraohgaki committed
            if (!appImageUpdater.hasError()) {
    
    akiraohgaki's avatar
    akiraohgaki committed
                if (newFilename != filename) {
                    auto installedItem = configHandler_->getUsrConfigInstalledItems()[itemKey].toObject();
                    QJsonArray files;
                    for (const auto &file : installedItem["files"].toArray()) {
                        if (file.toString() == filename) {
                            files.append(QJsonValue(newFilename));
                        }
                        else {
                            files.append(file);
                        }
                    }
                    installedItem["files"] = files;
                    configHandler_->setUsrConfigInstalledItemsItem(itemKey, installedItem);
                    qtlib::File(path).remove();
                }
    
                configHandler_->removeUsrConfigUpdateAvailableFile(fileKey);
    
    akiraohgaki's avatar
    akiraohgaki committed
            }
    
    akiraohgaki's avatar
    akiraohgaki committed
    
            emit updateFinished(fileKey);
    
    akiraohgaki's avatar
    akiraohgaki committed
        }
    
    akiraohgaki's avatar
    akiraohgaki committed
    }
    #endif