mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-06 05:01:25 -07:00
Merge pull request #22944 from sledgehammer999/fallback_update
Some checks are pending
CI - File health / Check (push) Waiting to run
CI - macOS / Build (push) Waiting to run
CI - Python / Check (push) Waiting to run
CI - Ubuntu / Build (push) Waiting to run
CI - WebUI / Check (push) Waiting to run
CI - Windows / Build (push) Waiting to run
Some checks are pending
CI - File health / Check (push) Waiting to run
CI - macOS / Build (push) Waiting to run
CI - Python / Check (push) Waiting to run
CI - Ubuntu / Build (push) Waiting to run
CI - WebUI / Check (push) Waiting to run
CI - Windows / Build (push) Waiting to run
Add fallback to update mechanism
This commit is contained in:
commit
a3e6d1a0ad
3 changed files with 79 additions and 26 deletions
|
@ -1662,11 +1662,11 @@ void MainWindow::handleUpdateCheckFinished(ProgramUpdater *updater, const bool i
|
||||||
updater->deleteLater();
|
updater->deleteLater();
|
||||||
};
|
};
|
||||||
|
|
||||||
const QString newVersion = updater->getNewVersion();
|
const auto newVersion = updater->getNewVersion();
|
||||||
if (!newVersion.isEmpty())
|
if (newVersion.isValid())
|
||||||
{
|
{
|
||||||
const QString msg {tr("A new version is available.") + u"<br/>"
|
const QString msg {tr("A new version is available.") + u"<br/>"
|
||||||
+ tr("Do you want to download %1?").arg(newVersion) + u"<br/><br/>"
|
+ tr("Do you want to download %1?").arg(newVersion.toString()) + u"<br/><br/>"
|
||||||
+ u"<a href=\"https://www.qbittorrent.org/news\">%1</a>"_s.arg(tr("Open changelog..."))};
|
+ u"<a href=\"https://www.qbittorrent.org/news\">%1</a>"_s.arg(tr("Open changelog..."))};
|
||||||
auto *msgBox = new QMessageBox {QMessageBox::Question, tr("qBittorrent Update Available"), msg
|
auto *msgBox = new QMessageBox {QMessageBox::Question, tr("qBittorrent Update Available"), msg
|
||||||
, (QMessageBox::Yes | QMessageBox::No), this};
|
, (QMessageBox::Yes | QMessageBox::No), this};
|
||||||
|
|
|
@ -35,10 +35,13 @@
|
||||||
#include <QtSystemDetection>
|
#include <QtSystemDetection>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonValue>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
|
|
||||||
#include "base/global.h"
|
#include "base/global.h"
|
||||||
|
#include "base/logger.h"
|
||||||
#include "base/net/downloadmanager.h"
|
#include "base/net/downloadmanager.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "base/utils/version.h"
|
#include "base/utils/version.h"
|
||||||
|
@ -46,23 +49,20 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
bool isVersionMoreRecent(const QString &remoteVersion)
|
bool isVersionMoreRecent(const ProgramUpdater::Version &remoteVersion)
|
||||||
{
|
{
|
||||||
using Version = Utils::Version<4, 3>;
|
if (!remoteVersion.isValid())
|
||||||
|
|
||||||
const auto newVersion = Version::fromString(remoteVersion);
|
|
||||||
if (!newVersion.isValid())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const Version currentVersion {QBT_VERSION_MAJOR, QBT_VERSION_MINOR, QBT_VERSION_BUGFIX, QBT_VERSION_BUILD};
|
const ProgramUpdater::Version currentVersion {QBT_VERSION_MAJOR, QBT_VERSION_MINOR, QBT_VERSION_BUGFIX, QBT_VERSION_BUILD};
|
||||||
if (newVersion == currentVersion)
|
if (remoteVersion == currentVersion)
|
||||||
{
|
{
|
||||||
const bool isDevVersion = QStringLiteral(QBT_VERSION_STATUS).contains(
|
const bool isDevVersion = QStringLiteral(QBT_VERSION_STATUS).contains(
|
||||||
QRegularExpression(u"(alpha|beta|rc)"_s));
|
QRegularExpression(u"(alpha|beta|rc)"_s));
|
||||||
if (isDevVersion)
|
if (isDevVersion)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return (newVersion > currentVersion);
|
return (remoteVersion > currentVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString buildVariant()
|
QString buildVariant()
|
||||||
|
@ -82,30 +82,34 @@ namespace
|
||||||
|
|
||||||
void ProgramUpdater::checkForUpdates() const
|
void ProgramUpdater::checkForUpdates() const
|
||||||
{
|
{
|
||||||
|
const auto USER_AGENT = QStringLiteral("qBittorrent/" QBT_VERSION_2 " ProgramUpdater (www.qbittorrent.org)");
|
||||||
const auto RSS_URL = u"https://www.fosshub.com/feed/5b8793a7f9ee5a5c3e97a3b2.xml"_s;
|
const auto RSS_URL = u"https://www.fosshub.com/feed/5b8793a7f9ee5a5c3e97a3b2.xml"_s;
|
||||||
|
const auto FALLBACK_URL = u"https://www.qbittorrent.org/versions.json"_s;
|
||||||
|
|
||||||
// Don't change this User-Agent. In case our updater goes haywire,
|
// Don't change this User-Agent. In case our updater goes haywire,
|
||||||
// the filehost can identify it and contact us.
|
// the filehost can identify it and contact us.
|
||||||
Net::DownloadManager::instance()->download(
|
Net::DownloadManager::instance()->download(Net::DownloadRequest(RSS_URL).userAgent(USER_AGENT)
|
||||||
Net::DownloadRequest(RSS_URL).userAgent(QStringLiteral("qBittorrent/" QBT_VERSION_2 " ProgramUpdater (www.qbittorrent.org)"))
|
|
||||||
, Preferences::instance()->useProxyForGeneralPurposes(), this, &ProgramUpdater::rssDownloadFinished);
|
, Preferences::instance()->useProxyForGeneralPurposes(), this, &ProgramUpdater::rssDownloadFinished);
|
||||||
|
Net::DownloadManager::instance()->download(Net::DownloadRequest(FALLBACK_URL).userAgent(USER_AGENT)
|
||||||
|
, Preferences::instance()->useProxyForGeneralPurposes(), this, &ProgramUpdater::fallbackDownloadFinished);
|
||||||
|
|
||||||
|
m_hasCompletedOneReq = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ProgramUpdater::getNewVersion() const
|
ProgramUpdater::Version ProgramUpdater::getNewVersion() const
|
||||||
{
|
{
|
||||||
return m_newVersion;
|
return shouldUseFallback() ? m_fallbackRemoteVersion : m_remoteVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgramUpdater::rssDownloadFinished(const Net::DownloadResult &result)
|
void ProgramUpdater::rssDownloadFinished(const Net::DownloadResult &result)
|
||||||
{
|
{
|
||||||
if (result.status != Net::DownloadStatus::Success)
|
if (result.status != Net::DownloadStatus::Success)
|
||||||
{
|
{
|
||||||
qDebug() << "Downloading the new qBittorrent updates RSS failed:" << result.errorString;
|
LogMsg(tr("Failed to download the update info. URL: %1. Error: %2").arg(result.url, result.errorString) , Log::WARNING);
|
||||||
emit updateCheckFinished();
|
handleFinishedRequest();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug("Finished downloading the new qBittorrent updates RSS");
|
|
||||||
|
|
||||||
const auto getStringValue = [](QXmlStreamReader &xml) -> QString
|
const auto getStringValue = [](QXmlStreamReader &xml) -> QString
|
||||||
{
|
{
|
||||||
xml.readNext();
|
xml.readNext();
|
||||||
|
@ -146,9 +150,10 @@ void ProgramUpdater::rssDownloadFinished(const Net::DownloadResult &result)
|
||||||
if (!version.isEmpty())
|
if (!version.isEmpty())
|
||||||
{
|
{
|
||||||
qDebug("Detected version is %s", qUtf8Printable(version));
|
qDebug("Detected version is %s", qUtf8Printable(version));
|
||||||
if (isVersionMoreRecent(version))
|
const ProgramUpdater::Version tmpVer {version};
|
||||||
|
if (isVersionMoreRecent(tmpVer))
|
||||||
{
|
{
|
||||||
m_newVersion = version;
|
m_remoteVersion = tmpVer;
|
||||||
m_updateURL = updateLink;
|
m_updateURL = updateLink;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,10 +168,50 @@ void ProgramUpdater::rssDownloadFinished(const Net::DownloadResult &result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit updateCheckFinished();
|
handleFinishedRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgramUpdater::fallbackDownloadFinished(const Net::DownloadResult &result)
|
||||||
|
{
|
||||||
|
if (result.status != Net::DownloadStatus::Success)
|
||||||
|
{
|
||||||
|
LogMsg(tr("Failed to download the update info. URL: %1. Error: %2").arg(result.url, result.errorString) , Log::WARNING);
|
||||||
|
handleFinishedRequest();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto json = QJsonDocument::fromJson(result.data);
|
||||||
|
|
||||||
|
#if defined(Q_OS_MACOS)
|
||||||
|
const QString platformKey = u"macos"_s;
|
||||||
|
#elif defined(Q_OS_WIN)
|
||||||
|
const QString platformKey = u"win"_s;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (const QJsonValue verJSON = json[platformKey][u"version"_s]; verJSON.isString())
|
||||||
|
{
|
||||||
|
const ProgramUpdater::Version tmpVer {verJSON.toString()};
|
||||||
|
if (isVersionMoreRecent(tmpVer))
|
||||||
|
m_fallbackRemoteVersion = tmpVer;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleFinishedRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProgramUpdater::updateProgram() const
|
bool ProgramUpdater::updateProgram() const
|
||||||
{
|
{
|
||||||
return QDesktopServices::openUrl(m_updateURL);
|
return QDesktopServices::openUrl(shouldUseFallback() ? u"https://www.qbittorrent.org/download"_s : m_updateURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgramUpdater::handleFinishedRequest()
|
||||||
|
{
|
||||||
|
if (m_hasCompletedOneReq)
|
||||||
|
emit updateCheckFinished();
|
||||||
|
else
|
||||||
|
m_hasCompletedOneReq = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProgramUpdater::shouldUseFallback() const
|
||||||
|
{
|
||||||
|
return m_fallbackRemoteVersion > m_remoteVersion;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "base/utils/version.h"
|
||||||
|
|
||||||
namespace Net
|
namespace Net
|
||||||
{
|
{
|
||||||
struct DownloadResult;
|
struct DownloadResult;
|
||||||
|
@ -45,9 +46,10 @@ class ProgramUpdater final : public QObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using QObject::QObject;
|
using QObject::QObject;
|
||||||
|
using Version = Utils::Version<4, 3>;
|
||||||
|
|
||||||
void checkForUpdates() const;
|
void checkForUpdates() const;
|
||||||
QString getNewVersion() const;
|
Version getNewVersion() const;
|
||||||
bool updateProgram() const;
|
bool updateProgram() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -55,8 +57,14 @@ signals:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void rssDownloadFinished(const Net::DownloadResult &result);
|
void rssDownloadFinished(const Net::DownloadResult &result);
|
||||||
|
void fallbackDownloadFinished(const Net::DownloadResult &result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_newVersion;
|
void handleFinishedRequest();
|
||||||
|
bool shouldUseFallback() const;
|
||||||
|
|
||||||
|
mutable bool m_hasCompletedOneReq = false;
|
||||||
|
Version m_remoteVersion;
|
||||||
|
Version m_fallbackRemoteVersion;
|
||||||
QUrl m_updateURL;
|
QUrl m_updateURL;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue