1
Fork 0
mirror of https://github.com/redstrate/Astra.git synced 2025-04-21 20:27:45 +00:00

Move fetchAvatar from Account to LauncherCore

This is to head towards removing the LauncherCore dependency inside of
Account (and by extension, AccountManager.) This function should really
belong here anyway, since it uses a lot of functionality from
LauncherCore.
This commit is contained in:
Joshua Goins 2024-08-22 18:46:45 -04:00
parent 9876cb0aab
commit c602f01062
6 changed files with 74 additions and 57 deletions

View file

@ -74,6 +74,8 @@ public:
Q_INVOKABLE QString getPassword(); Q_INVOKABLE QString getPassword();
void setPassword(const QString &password); void setPassword(const QString &password);
void setAvatarUrl(const QString &url);
Q_INVOKABLE QString getOTP(); Q_INVOKABLE QString getOTP();
Q_INVOKABLE void setOTPSecret(const QString &secret); Q_INVOKABLE void setOTPSecret(const QString &secret);
@ -101,7 +103,6 @@ Q_SIGNALS:
bool needsPasswordChanged(); bool needsPasswordChanged();
private: private:
void fetchAvatar();
QCoro::Task<> fetchPassword(); QCoro::Task<> fetchPassword();
/** /**

View file

@ -43,6 +43,8 @@ public:
Q_SIGNALS: Q_SIGNALS:
void accountsChanged(); void accountsChanged();
void accountAdded(Account *account);
void accountLodestoneIdChanged(Account *account);
private: private:
void insertAccount(Account *account); void insertAccount(Account *account);

View file

@ -99,7 +99,10 @@ public:
Q_INVOKABLE BenchmarkInstaller *createBenchmarkInstaller(Profile *profile); Q_INVOKABLE BenchmarkInstaller *createBenchmarkInstaller(Profile *profile);
Q_INVOKABLE BenchmarkInstaller *createBenchmarkInstallerFromExisting(Profile *profile, const QString &filePath); Q_INVOKABLE BenchmarkInstaller *createBenchmarkInstallerFromExisting(Profile *profile, const QString &filePath);
/// Fetches the avatar for @p account
void fetchAvatar(Account *account);
Q_INVOKABLE void clearAvatarCache(); Q_INVOKABLE void clearAvatarCache();
Q_INVOKABLE void refreshNews(); Q_INVOKABLE void refreshNews();
Q_INVOKABLE void refreshLogoImage(); Q_INVOKABLE void refreshLogoImage();

View file

@ -21,7 +21,6 @@ Account::Account(LauncherCore &launcher, const QString &key, QObject *parent)
, m_key(key) , m_key(key)
, m_launcher(launcher) , m_launcher(launcher)
{ {
fetchAvatar();
fetchPassword(); fetchPassword();
} }
@ -68,7 +67,6 @@ void Account::setLodestoneId(const QString &id)
if (m_config.lodestoneId() != id) { if (m_config.lodestoneId() != id) {
m_config.setLodestoneId(id); m_config.setLodestoneId(id);
m_config.save(); m_config.save();
fetchAvatar();
Q_EMIT lodestoneIdChanged(); Q_EMIT lodestoneIdChanged();
} }
} }
@ -191,6 +189,14 @@ void Account::setPassword(const QString &password)
} }
} }
void Account::setAvatarUrl(const QString &url)
{
if (m_avatarUrl != url) {
m_avatarUrl = url;
Q_EMIT avatarUrlChanged();
}
}
QString Account::getOTP() QString Account::getOTP()
{ {
const auto otpSecret = QCoro::waitFor(getKeychainValue(QStringLiteral("otp-secret"))); const auto otpSecret = QCoro::waitFor(getKeychainValue(QStringLiteral("otp-secret")));
@ -227,60 +233,6 @@ QString Account::getConfigPath() const
return getConfigDir().absolutePath(); return getConfigDir().absolutePath();
} }
void Account::fetchAvatar()
{
if (lodestoneId().isEmpty()) {
return;
}
const QString cacheLocation = QStandardPaths::standardLocations(QStandardPaths::CacheLocation)[0] + QStringLiteral("/avatars");
Utility::createPathIfNeeded(cacheLocation);
const QString filename = QStringLiteral("%1/%2.jpg").arg(cacheLocation, lodestoneId());
if (!QFile(filename).exists()) {
qDebug(ASTRA_LOG) << "Did not find lodestone character " << lodestoneId() << " in cache, fetching from Lodestone.";
QUrl url;
url.setScheme(m_launcher.settings()->preferredProtocol());
url.setHost(QStringLiteral("na.%1").arg(m_launcher.settings()->mainServer())); // TODO: NA isnt the only thing in the world...
url.setPath(QStringLiteral("/lodestone/character/%1").arg(lodestoneId()));
const QNetworkRequest request(url);
Utility::printRequest(QStringLiteral("GET"), request);
const auto reply = m_launcher.mgr()->get(request);
connect(reply, &QNetworkReply::finished, [this, filename, reply] {
const QString document = QString::fromUtf8(reply->readAll());
if (!document.isEmpty()) {
const static QRegularExpression re(
QStringLiteral(R"lit(<div\s[^>]*class=["|']frame__chara__face["|'][^>]*>\s*<img\s[&>]*src=["|']([^"']*))lit"));
const QRegularExpressionMatch match = re.match(document);
if (match.hasCaptured(1)) {
const QString newAvatarUrl = match.captured(1);
const auto avatarRequest = QNetworkRequest(QUrl(newAvatarUrl));
Utility::printRequest(QStringLiteral("GET"), avatarRequest);
auto avatarReply = m_launcher.mgr()->get(avatarRequest);
connect(avatarReply, &QNetworkReply::finished, [this, filename, avatarReply] {
QFile file(filename);
file.open(QIODevice::ReadWrite);
file.write(avatarReply->readAll());
file.close();
m_avatarUrl = QStringLiteral("file:///%1").arg(filename);
Q_EMIT avatarUrlChanged();
});
}
}
});
} else {
m_avatarUrl = QStringLiteral("file:///%1").arg(filename);
Q_EMIT avatarUrlChanged();
}
}
void Account::setKeychainValue(const QString &key, const QString &value) void Account::setKeychainValue(const QString &key, const QString &value)
{ {
if (m_launcher.isSteamDeck()) { if (m_launcher.isSteamDeck()) {

View file

@ -111,10 +111,14 @@ void AccountManager::deleteAccount(Account *account)
void AccountManager::insertAccount(Account *account) void AccountManager::insertAccount(Account *account)
{ {
connect(account, &Account::avatarUrlChanged, this, [this, account] {
Q_EMIT accountLodestoneIdChanged(account);
});
beginInsertRows(QModelIndex(), static_cast<int>(m_accounts.size()), static_cast<int>(m_accounts.size())); beginInsertRows(QModelIndex(), static_cast<int>(m_accounts.size()), static_cast<int>(m_accounts.size()));
m_accounts.append(account); m_accounts.append(account);
endInsertRows(); endInsertRows();
Q_EMIT accountsChanged(); Q_EMIT accountsChanged();
Q_EMIT accountAdded(account);
} }
bool AccountManager::hasAnyAccounts() const bool AccountManager::hasAnyAccounts() const

View file

@ -40,6 +40,9 @@ LauncherCore::LauncherCore()
m_accountManager = new AccountManager(*this, this); m_accountManager = new AccountManager(*this, this);
m_runner = new GameRunner(*this, this); m_runner = new GameRunner(*this, this);
connect(m_accountManager, &AccountManager::accountAdded, this, &LauncherCore::fetchAvatar);
connect(m_accountManager, &AccountManager::accountLodestoneIdChanged, this, &LauncherCore::fetchAvatar);
connect(this, &LauncherCore::gameClosed, this, &LauncherCore::handleGameExit); connect(this, &LauncherCore::gameClosed, this, &LauncherCore::handleGameExit);
#ifdef BUILD_SYNC #ifdef BUILD_SYNC
@ -154,6 +157,58 @@ BenchmarkInstaller *LauncherCore::createBenchmarkInstallerFromExisting(Profile *
return new BenchmarkInstaller(*this, *profile, filePath, this); return new BenchmarkInstaller(*this, *profile, filePath, this);
} }
void LauncherCore::fetchAvatar(Account *account)
{
if (account->lodestoneId().isEmpty()) {
return;
}
const QString cacheLocation = QStandardPaths::standardLocations(QStandardPaths::CacheLocation)[0] + QStringLiteral("/avatars");
Utility::createPathIfNeeded(cacheLocation);
const QString filename = QStringLiteral("%1/%2.jpg").arg(cacheLocation, account->lodestoneId());
if (!QFile(filename).exists()) {
qDebug(ASTRA_LOG) << "Did not find lodestone character " << account->lodestoneId() << " in cache, fetching from Lodestone.";
QUrl url;
url.setScheme(settings()->preferredProtocol());
url.setHost(QStringLiteral("na.%1").arg(settings()->mainServer())); // TODO: NA isnt the only thing in the world...
url.setPath(QStringLiteral("/lodestone/character/%1").arg(account->lodestoneId()));
const QNetworkRequest request(url);
Utility::printRequest(QStringLiteral("GET"), request);
const auto reply = mgr()->get(request);
connect(reply, &QNetworkReply::finished, [this, filename, reply, account] {
const QString document = QString::fromUtf8(reply->readAll());
if (!document.isEmpty()) {
const static QRegularExpression re(
QStringLiteral(R"lit(<div\s[^>]*class=["|']frame__chara__face["|'][^>]*>\s*<img\s[&>]*src=["|']([^"']*))lit"));
const QRegularExpressionMatch match = re.match(document);
if (match.hasCaptured(1)) {
const QString newAvatarUrl = match.captured(1);
const auto avatarRequest = QNetworkRequest(QUrl(newAvatarUrl));
Utility::printRequest(QStringLiteral("GET"), avatarRequest);
auto avatarReply = mgr()->get(avatarRequest);
connect(avatarReply, &QNetworkReply::finished, [this, filename, avatarReply, account] {
QFile file(filename);
file.open(QIODevice::ReadWrite);
file.write(avatarReply->readAll());
file.close();
account->setAvatarUrl(QStringLiteral("file:///%1").arg(filename));
});
}
}
});
} else {
account->setAvatarUrl(QStringLiteral("file:///%1").arg(filename));
}
}
void LauncherCore::clearAvatarCache() void LauncherCore::clearAvatarCache()
{ {
const QString cacheLocation = QStandardPaths::standardLocations(QStandardPaths::CacheLocation)[0] + QStringLiteral("/avatars"); const QString cacheLocation = QStandardPaths::standardLocations(QStandardPaths::CacheLocation)[0] + QStringLiteral("/avatars");