2023-08-05 22:14:05 -04:00
|
|
|
// SPDX-FileCopyrightText: 2023 Joshua Goins <josh@redstrate.com>
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
2021-11-23 14:37:37 -05:00
|
|
|
#include "assetupdater.h"
|
2023-10-08 18:54:03 -04:00
|
|
|
#include "astra_log.h"
|
2023-10-08 18:02:02 -04:00
|
|
|
#include "utility.h"
|
2021-11-23 14:37:37 -05:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
#include <KLocalizedString>
|
2021-11-23 14:37:37 -05:00
|
|
|
#include <QFile>
|
2022-01-27 10:46:22 -05:00
|
|
|
#include <QJsonDocument>
|
2022-02-23 19:05:53 -05:00
|
|
|
#include <QNetworkReply>
|
|
|
|
#include <QStandardPaths>
|
2023-09-17 18:43:58 -04:00
|
|
|
#include <qcorofuture.h>
|
|
|
|
#include <qcoronetworkreply.h>
|
2021-11-23 14:37:37 -05:00
|
|
|
|
2022-03-01 16:43:49 -05:00
|
|
|
#include <JlCompress.h>
|
2023-09-17 18:43:58 -04:00
|
|
|
#include <QtConcurrentRun>
|
2021-11-23 14:37:37 -05:00
|
|
|
|
2023-07-30 08:49:34 -04:00
|
|
|
AssetUpdater::AssetUpdater(Profile &profile, LauncherCore &launcher, QObject *parent)
|
|
|
|
: QObject(parent)
|
|
|
|
, launcher(launcher)
|
2023-09-17 09:02:11 -04:00
|
|
|
, chosenChannel(profile.dalamudChannel())
|
2023-07-30 08:49:34 -04:00
|
|
|
, m_profile(profile)
|
|
|
|
{
|
2023-09-17 18:43:58 -04:00
|
|
|
}
|
|
|
|
|
2023-10-08 19:07:34 -04:00
|
|
|
QCoro::Task<bool> AssetUpdater::update()
|
2023-09-17 18:43:58 -04:00
|
|
|
{
|
|
|
|
if (!m_profile.dalamudEnabled()) {
|
2023-10-08 19:07:34 -04:00
|
|
|
co_return true;
|
2023-09-17 18:43:58 -04:00
|
|
|
}
|
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
qInfo(ASTRA_LOG) << "Checking for asset updates...";
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
2023-09-17 18:43:58 -04:00
|
|
|
dalamudDir = dataDir.absoluteFilePath(QStringLiteral("dalamud"));
|
|
|
|
dalamudAssetDir = dalamudDir.absoluteFilePath(QStringLiteral("assets"));
|
|
|
|
dalamudRuntimeDir = dalamudDir.absoluteFilePath(QStringLiteral("runtime"));
|
2023-08-18 14:52:06 -04:00
|
|
|
|
|
|
|
const auto createIfNeeded = [](const QDir &dir) {
|
|
|
|
if (!QDir().exists(dir.absolutePath()))
|
2023-09-17 18:43:58 -04:00
|
|
|
QDir().mkpath(dir.absolutePath());
|
2023-08-18 14:52:06 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
createIfNeeded(dalamudDir);
|
|
|
|
createIfNeeded(dalamudAssetDir);
|
|
|
|
createIfNeeded(dalamudRuntimeDir);
|
2023-09-17 18:43:58 -04:00
|
|
|
|
2023-10-08 19:07:34 -04:00
|
|
|
if (!co_await checkRemoteDalamudAssetVersion()) {
|
|
|
|
co_return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!co_await checkRemoteDalamudVersion()) {
|
|
|
|
co_return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
co_return true;
|
2021-11-23 14:37:37 -05:00
|
|
|
}
|
|
|
|
|
2023-10-08 19:07:34 -04:00
|
|
|
QCoro::Task<bool> AssetUpdater::checkRemoteDalamudAssetVersion()
|
2023-07-30 08:49:34 -04:00
|
|
|
{
|
2023-09-17 18:43:58 -04:00
|
|
|
// first we want to fetch the list of assets required
|
|
|
|
const QNetworkRequest request(dalamudAssetManifestUrl());
|
2023-10-08 18:02:02 -04:00
|
|
|
Utility::printRequest(QStringLiteral("GET"), request);
|
2021-11-23 14:37:37 -05:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
const auto reply = launcher.mgr->get(request);
|
|
|
|
co_await reply;
|
2022-02-23 19:05:53 -05:00
|
|
|
|
2023-10-08 19:07:34 -04:00
|
|
|
if (reply->error() != QNetworkReply::NetworkError::NoError) {
|
|
|
|
Q_EMIT launcher.dalamudError(i18n("Could not check for Dalamud asset updates.\n\n%1", reply->errorString()));
|
|
|
|
co_return false;
|
|
|
|
}
|
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
|
2022-02-25 18:08:57 -05:00
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
remoteDalamudAssetVersion = doc.object()[QLatin1String("version")].toInt();
|
|
|
|
remoteDalamudAssetArray = doc.object()[QLatin1String("assets")].toArray();
|
2022-02-25 18:08:57 -05:00
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
qInfo(ASTRA_LOG) << "Dalamud asset remote version" << remoteDalamudAssetVersion;
|
|
|
|
qInfo(ASTRA_LOG) << "Dalamud asset local version" << m_profile.dalamudAssetVersion();
|
2022-02-25 18:08:57 -05:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
// dalamud assets
|
|
|
|
if (remoteDalamudAssetVersion != m_profile.dalamudAssetVersion()) {
|
2023-10-08 18:54:03 -04:00
|
|
|
qInfo(ASTRA_LOG) << "Dalamud assets out of date";
|
2022-02-25 20:06:29 -05:00
|
|
|
|
2023-10-08 19:07:34 -04:00
|
|
|
co_return co_await installDalamudAssets();
|
2021-11-23 14:37:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-08 19:07:34 -04:00
|
|
|
QCoro::Task<bool> AssetUpdater::checkRemoteDalamudVersion()
|
2023-07-30 08:49:34 -04:00
|
|
|
{
|
2023-10-08 18:54:03 -04:00
|
|
|
QUrl url(dalamudVersionManifestUrl());
|
|
|
|
|
|
|
|
QUrlQuery query;
|
|
|
|
query.addQueryItem(QStringLiteral("track"), m_profile.dalamudChannelName());
|
|
|
|
|
|
|
|
const QNetworkRequest request(url);
|
2023-10-08 18:02:02 -04:00
|
|
|
Utility::printRequest(QStringLiteral("GET"), request);
|
2022-02-25 20:06:29 -05:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
remoteDalamudVersion.clear();
|
|
|
|
remoteRuntimeVersion.clear();
|
2022-02-25 20:06:29 -05:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
const auto reply = launcher.mgr->get(request);
|
|
|
|
co_await reply;
|
2022-02-25 20:06:29 -05:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
if (reply->error() != QNetworkReply::NetworkError::NoError) {
|
2023-10-08 19:07:34 -04:00
|
|
|
Q_EMIT launcher.dalamudError(i18n("Could not check for Dalamud updates.\n\n%1", reply->errorString()));
|
|
|
|
co_return false;
|
2022-02-25 20:06:29 -05:00
|
|
|
}
|
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
|
|
|
|
remoteDalamudVersion = doc[QLatin1String("assemblyVersion")].toString();
|
|
|
|
remoteRuntimeVersion = doc[QLatin1String("runtimeVersion")].toString();
|
|
|
|
remoteDalamudDownloadUrl = doc[QLatin1String("downloadUrl")].toString();
|
2022-03-13 20:48:43 -04:00
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
qInfo(ASTRA_LOG) << "Latest available Dalamud version:" << remoteDalamudVersion << "local:" << m_profile.dalamudVersion();
|
|
|
|
qInfo(ASTRA_LOG) << "Latest available NET runtime:" << remoteRuntimeVersion;
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
if (remoteDalamudVersion != m_profile.dalamudVersion()) {
|
2023-10-08 19:07:34 -04:00
|
|
|
if (!co_await installDalamud()) {
|
|
|
|
co_return false;
|
|
|
|
}
|
2023-09-17 18:43:58 -04:00
|
|
|
}
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 08:51:26 -04:00
|
|
|
if (m_profile.runtimeVersion() != remoteRuntimeVersion) {
|
2023-10-08 19:07:34 -04:00
|
|
|
if (!co_await installRuntime()) {
|
|
|
|
co_return false;
|
|
|
|
}
|
2023-09-17 18:43:58 -04:00
|
|
|
}
|
2023-10-08 19:07:34 -04:00
|
|
|
|
|
|
|
co_return true;
|
2023-09-17 18:43:58 -04:00
|
|
|
}
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-10-08 19:07:34 -04:00
|
|
|
QCoro::Task<bool> AssetUpdater::installDalamudAssets()
|
2023-09-17 18:43:58 -04:00
|
|
|
{
|
|
|
|
Q_EMIT launcher.stageChanged(i18n("Updating Dalamud assets..."));
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
QFutureSynchronizer<void> synchronizer;
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
for (const auto &assetObject : remoteDalamudAssetArray) {
|
2023-10-08 18:54:03 -04:00
|
|
|
const QNetworkRequest assetRequest(assetObject.toObject()[QLatin1String("url")].toString());
|
2023-10-08 18:02:02 -04:00
|
|
|
Utility::printRequest(QStringLiteral("GET"), assetRequest);
|
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
const auto assetReply = launcher.mgr->get(assetRequest);
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
const auto future = QtFuture::connect(assetReply, &QNetworkReply::finished).then([this, assetReply, assetObject] {
|
2023-10-08 18:54:03 -04:00
|
|
|
const QString fileName = assetObject.toObject()[QLatin1String("fileName")].toString();
|
2023-09-17 18:43:58 -04:00
|
|
|
const QString dirPath = fileName.left(fileName.lastIndexOf(QLatin1Char('/')));
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
const QString path = dalamudAssetDir.absoluteFilePath(dirPath);
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
if (!QDir().exists(path))
|
|
|
|
QDir().mkpath(path);
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
QFile file(dalamudAssetDir.absoluteFilePath(assetObject.toObject()[QLatin1String("fileName")].toString()));
|
2023-09-17 18:43:58 -04:00
|
|
|
file.open(QIODevice::WriteOnly);
|
|
|
|
file.write(assetReply->readAll());
|
|
|
|
file.close();
|
|
|
|
});
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
synchronizer.addFuture(future);
|
2022-03-13 20:44:57 -04:00
|
|
|
}
|
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
co_await QtConcurrent::run([&synchronizer] {
|
|
|
|
synchronizer.waitForFinished();
|
|
|
|
});
|
2022-04-08 19:34:51 -04:00
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
qInfo(ASTRA_LOG) << "Finished downloading Dalamud assets";
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
m_profile.setDalamudAssetVersion(remoteDalamudAssetVersion);
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
QFile file(dalamudAssetDir.absoluteFilePath(QStringLiteral("asset.ver")));
|
|
|
|
file.open(QIODevice::WriteOnly | QIODevice::Text);
|
|
|
|
file.write(QString::number(remoteDalamudAssetVersion).toUtf8());
|
|
|
|
file.close();
|
2023-10-08 19:07:34 -04:00
|
|
|
|
|
|
|
co_return true;
|
2023-09-17 18:43:58 -04:00
|
|
|
}
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-10-08 19:07:34 -04:00
|
|
|
QCoro::Task<bool> AssetUpdater::installDalamud()
|
2023-09-17 18:43:58 -04:00
|
|
|
{
|
|
|
|
Q_EMIT launcher.stageChanged(i18n("Updating Dalamud..."));
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
const QNetworkRequest request(remoteDalamudDownloadUrl);
|
2023-10-08 18:02:02 -04:00
|
|
|
Utility::printRequest(QStringLiteral("GET"), request);
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
const auto reply = launcher.mgr->get(request);
|
|
|
|
co_await reply;
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
qInfo(ASTRA_LOG) << "Finished downloading Dalamud";
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
QFile file(tempDir.path() + QStringLiteral("/latest.zip"));
|
|
|
|
file.open(QIODevice::WriteOnly);
|
|
|
|
file.write(reply->readAll());
|
|
|
|
file.close();
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
const bool success =
|
|
|
|
!JlCompress::extractDir(tempDir.path() + QLatin1String("/latest.zip"), dalamudDir.absoluteFilePath(m_profile.dalamudChannelName())).empty();
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
if (!success) {
|
2023-10-08 19:07:34 -04:00
|
|
|
qCritical(ASTRA_LOG) << "Failed to install Dalamud";
|
|
|
|
Q_EMIT launcher.dalamudError(i18n("Failed to install Dalamud."));
|
|
|
|
co_return false;
|
2022-03-13 20:44:57 -04:00
|
|
|
}
|
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
m_profile.setDalamudVersion(remoteDalamudVersion);
|
2023-10-08 19:07:34 -04:00
|
|
|
|
|
|
|
co_return true;
|
2023-09-17 18:43:58 -04:00
|
|
|
}
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-10-08 19:07:34 -04:00
|
|
|
QCoro::Task<bool> AssetUpdater::installRuntime()
|
2023-09-17 18:43:58 -04:00
|
|
|
{
|
|
|
|
Q_EMIT launcher.stageChanged(i18n("Updating .NET Runtime..."));
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
// core
|
|
|
|
{
|
2023-10-08 18:54:03 -04:00
|
|
|
const QNetworkRequest request(dotnetRuntimePackageUrl(remoteRuntimeVersion));
|
2023-10-08 18:02:02 -04:00
|
|
|
Utility::printRequest(QStringLiteral("GET"), request);
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
const auto reply = launcher.mgr->get(request);
|
|
|
|
co_await reply;
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
qInfo(ASTRA_LOG) << "Finished downloading Dotnet-core";
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
QFile file(tempDir.path() + QStringLiteral("/dotnet-core.zip"));
|
|
|
|
file.open(QIODevice::WriteOnly);
|
|
|
|
file.write(reply->readAll());
|
|
|
|
file.close();
|
|
|
|
}
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
// desktop
|
|
|
|
{
|
2023-10-08 18:54:03 -04:00
|
|
|
const QNetworkRequest request(dotnetDesktopPackageUrl(remoteRuntimeVersion));
|
2023-10-08 18:02:02 -04:00
|
|
|
Utility::printRequest(QStringLiteral("GET"), request);
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
const auto reply = launcher.mgr->get(request);
|
|
|
|
co_await reply;
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
qInfo(ASTRA_LOG) << "Finished downloading Dotnet-desktop";
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
QFile file(tempDir.path() + QStringLiteral("/dotnet-desktop.zip"));
|
|
|
|
file.open(QIODevice::WriteOnly);
|
|
|
|
file.write(reply->readAll());
|
|
|
|
file.close();
|
|
|
|
}
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
bool success = !JlCompress::extractDir(tempDir.path() + QStringLiteral("/dotnet-core.zip"), dalamudRuntimeDir.absolutePath()).empty();
|
|
|
|
success |= !JlCompress::extractDir(tempDir.path() + QStringLiteral("/dotnet-desktop.zip"), dalamudRuntimeDir.absolutePath()).empty();
|
2022-03-13 20:44:57 -04:00
|
|
|
|
2023-09-17 18:43:58 -04:00
|
|
|
if (!success) {
|
2023-10-08 19:07:34 -04:00
|
|
|
qCritical(ASTRA_LOG) << "Failed to install dotnet";
|
|
|
|
Q_EMIT launcher.dalamudError(i18n("Failed to install .NET runtime."));
|
|
|
|
|
|
|
|
co_return false;
|
2023-09-17 18:43:58 -04:00
|
|
|
} else {
|
|
|
|
QFile file(dalamudRuntimeDir.absoluteFilePath(QStringLiteral("runtime.ver")));
|
|
|
|
file.open(QIODevice::WriteOnly | QIODevice::Text);
|
|
|
|
file.write(remoteRuntimeVersion.toUtf8());
|
|
|
|
file.close();
|
2023-10-08 19:07:34 -04:00
|
|
|
|
|
|
|
co_return true;
|
2022-03-13 20:44:57 -04:00
|
|
|
}
|
2022-02-25 18:08:57 -05:00
|
|
|
}
|
2023-08-18 21:36:29 -04:00
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
QUrl AssetUpdater::dalamudVersionManifestUrl() const
|
|
|
|
{
|
|
|
|
QUrl url;
|
|
|
|
url.setScheme(launcher.preferredProtocol());
|
|
|
|
url.setHost(launcher.dalamudDistribServer());
|
|
|
|
url.setPath(QStringLiteral("/Dalamud/Release/VersionInfo"));
|
2023-08-18 21:36:29 -04:00
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
QUrl AssetUpdater::dalamudAssetManifestUrl() const
|
2023-08-18 21:36:29 -04:00
|
|
|
{
|
|
|
|
QUrl url;
|
2023-10-06 18:14:32 -04:00
|
|
|
url.setScheme(launcher.preferredProtocol());
|
2023-08-18 21:36:29 -04:00
|
|
|
url.setHost(launcher.dalamudDistribServer());
|
2023-10-08 18:54:03 -04:00
|
|
|
url.setPath(QStringLiteral("/Dalamud/Asset/Meta"));
|
2023-08-18 21:36:29 -04:00
|
|
|
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
QUrl AssetUpdater::dotnetRuntimePackageUrl(const QString &version) const
|
2023-08-18 21:36:29 -04:00
|
|
|
{
|
|
|
|
QUrl url;
|
2023-10-06 18:14:32 -04:00
|
|
|
url.setScheme(launcher.preferredProtocol());
|
2023-08-18 21:36:29 -04:00
|
|
|
url.setHost(launcher.dalamudDistribServer());
|
2023-10-08 18:54:03 -04:00
|
|
|
url.setPath(QStringLiteral("/Dalamud/Release/Runtime/DotNet/%1").arg(version));
|
2023-08-18 21:36:29 -04:00
|
|
|
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
2023-10-08 18:54:03 -04:00
|
|
|
QUrl AssetUpdater::dotnetDesktopPackageUrl(const QString &version) const
|
2023-08-18 21:36:29 -04:00
|
|
|
{
|
|
|
|
QUrl url;
|
2023-10-06 18:14:32 -04:00
|
|
|
url.setScheme(launcher.preferredProtocol());
|
2023-08-18 21:36:29 -04:00
|
|
|
url.setHost(launcher.dalamudDistribServer());
|
2023-10-08 18:54:03 -04:00
|
|
|
url.setPath(QStringLiteral("/Dalamud/Release/Runtime/WindowsDesktop/%1").arg(version));
|
2023-08-18 21:36:29 -04:00
|
|
|
|
|
|
|
return url;
|
|
|
|
}
|