Skip to content
Snippets Groups Projects
updatehandler.cpp 6.1 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
    #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();
    
        auto application = configHandler_->getUsrConfigApplication();
        auto installedItems = configHandler_->getUsrConfigInstalledItems();
    
    
    akiraohgaki's avatar
    akiraohgaki committed
        if (installedItems.isEmpty() || application.contains("update_checked_at")) {
            auto currentDate = QDateTime::currentDateTime();
            auto checkedDate = QDateTime::fromMSecsSinceEpoch(application["update_checked_at"].toInt());
            if (currentDate.daysTo(checkedDate.addDays(1)) <= 0) {
                emit checkAllFinished();
                return;
            }
    
    akiraohgaki's avatar
    akiraohgaki committed
        }
    
        // 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)) {
    
    akiraohgaki's avatar
    akiraohgaki committed
            auto updateMethod = configHandler_->getUsrConfigUpdateAvailable()[fileKey].toObject()["update_method"].toString();
    
    akiraohgaki's avatar
    akiraohgaki committed
    
    #ifdef QTLIB_UNIX
    
    akiraohgaki's avatar
    akiraohgaki committed
            if (updateMethod == "appimageupdate") {
    
    akiraohgaki's avatar
    akiraohgaki committed
                updateAppImage(fileKey);
            }
    
    akiraohgaki's avatar
    akiraohgaki committed
            //else if (updateMethod == "appimageupdatewithocsapi") {
            //}
    
    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 &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)) {
    
    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(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()) {
    
    akiraohgaki's avatar
    akiraohgaki committed
                QThread::msleep(100);
    
    akiraohgaki's avatar
    akiraohgaki committed
                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;
    
    akiraohgaki's avatar
    akiraohgaki committed
                    installedItem["installed_at"] = QDateTime::currentMSecsSinceEpoch();
    
    akiraohgaki's avatar
    akiraohgaki committed
                    configHandler_->setUsrConfigInstalledItemsItem(itemKey, installedItem);
                    qtlib::File(path).remove();
                }
    
                configHandler_->removeUsrConfigUpdateAvailableFile(fileKey);
    
    akiraohgaki's avatar
    akiraohgaki committed
            }
    
    akiraohgaki's avatar
    akiraohgaki committed
            else {
                std::string nextMessage;
                while (appImageUpdater.nextStatusMessage(nextMessage)) {
                    qWarning() << QString::fromStdString(nextMessage);
                }
            }
    
    akiraohgaki's avatar
    akiraohgaki committed
    
            emit updateFinished(fileKey);
    
    akiraohgaki's avatar
    akiraohgaki committed
        }
    
    akiraohgaki's avatar
    akiraohgaki committed
    }
    #endif