mirror of
https://github.com/redstrate/Astra.git
synced 2025-05-17 14:47:45 +00:00
Grab steam ticket from steamwrap, give it to the oauth top API
This puts everything in place now, and yet Square Enix refuses to my session still :-(
This commit is contained in:
parent
3d39887d9c
commit
05d33dc5d7
8 changed files with 39 additions and 43 deletions
|
@ -15,8 +15,6 @@ plugins!
|
||||||
* Game Patching Support: Can patch the game without the need to boot into the official launcher.
|
* Game Patching Support: Can patch the game without the need to boot into the official launcher.
|
||||||
* Alternative Server Support: Can use alternative servers in case the official ones ever disappear.
|
* Alternative Server Support: Can use alternative servers in case the official ones ever disappear.
|
||||||
|
|
||||||
**Note:** Steam-linked Square Enix accounts are not currently supported. You will have to use the official launcher or XIVLauncher.Core.
|
|
||||||
|
|
||||||
## Get It
|
## Get It
|
||||||
|
|
||||||
Details on where to find stable releases of Astra can be found on its [homepage](https://xiv.zone/astra/install).
|
Details on where to find stable releases of Astra can be found on its [homepage](https://xiv.zone/astra/install).
|
||||||
|
|
|
@ -12,30 +12,37 @@ class EncryptedArgTest : public QObject
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void steamTicket_data()
|
void steamTicket_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QByteArray>("ticketBytes");
|
QTest::addColumn<QString>("ticketBytes");
|
||||||
QTest::addColumn<uint32_t>("time");
|
QTest::addColumn<uint32_t>("time");
|
||||||
QTest::addColumn<QString>("encryptedTicket");
|
QTest::addColumn<QString>("encryptedTicket");
|
||||||
|
QTest::addColumn<int>("encryptedLength");
|
||||||
|
|
||||||
QTest::addRow("test 1") << QByteArrayLiteral(
|
QTest::addRow("real ticket")
|
||||||
"caf59103e80d600b4a9233358c131a437cedcf8802eb705223cce84278e6cb4c3655a7accd98097c06748b33d340f9de79920754616e295b88b833d9d84412ffc6a4406c60a6691ce5"
|
<< QStringLiteral(
|
||||||
"2c27b5b1c90d36a6a810cef4c81fdc3c75aaa87353433f2f3c7232c00d1198a79bb27df6edb89c5fd0a3a11e957c40")
|
"140000009efb2c79d200f07599f633050100100195c517681800000001000000020000002c9ea991afec1a49f7e72d000b000000b8000000380000000400000099f63305010"
|
||||||
<< static_cast<uint32_t>(1746386404)
|
"010012a990000c47323496501a8c000000000807a1268002a2e680100908400000100c5000400000000004e408e518c259b8b329b5fcfdb00903fadad36d7e088813dc9b174"
|
||||||
<< QStringLiteral(
|
"b06e08b69f8f46d083cf4118d1eb4062e009147906d9c80759af3eb221f7fbb8e28d402e11ba80e3cf4a101487f87ccce9688daf99dd412e6bcaab6e58f70030ff99323e4c8"
|
||||||
"jX6TeGNIJFgecYIQU4YLSnhkbCpTihoIBB6Dw5iw7rAWQiULVB-NhOsfJwLh7EHW5wYwU1XRJAy5dw6JCWQ6v0R5SwP_84DIVDT5gfET_"
|
"1824659f7aa89188fadc6402bcb540843e1578cd112d4536fd65c4bd926f754")
|
||||||
"BoXmUr7rfXtJF62vpZ16XfwH2-P2KlaVRTaSYQ8xqTqC_fef6agOdYHvL_g-cNyjjv3xTMsekWnDCDhdG3Y1NvnPcXdAX9v0pjHUu5W5-"
|
<< static_cast<uint32_t>(1746389891)
|
||||||
"k8iZhUeTcTjYhMODBPNXz6uf7mKd1wkwAsTnDZoL89k8U1asq78hyaiWsFb4Nb39vK0n0TZfb20yFoXZh9NRO2VpgS,dSTy86oaqm2ZjKu7FnnHmFU6R_"
|
<< QStringLiteral(
|
||||||
"lS8pk8EB6itIekPAfC37LYSBIEI1rT9cEvoXNkX6hIGnZ5sthiNPoi5nx9_HdjWYQ9R0Kar-Bgjeu77Av753T0GpVhJhYFyBkMe-"
|
"Tjr8Lv1O0HjJ7U4dOfkA9BdLAnEaCl_TU0GnYGGLTBM06TV9Ggf-fYb7WMqD-Xv758Q1zzSPTeaJctl8au-"
|
||||||
"NAqGMEjkYFjRUwOX9pEJGEszEL3_mWEbryQ8wL4ZaYk5xu4HAXe5hRwk-JUv__BW8IpiR_OsphQUgeKtRmXUPw1eIU2NYdsd3AJLAP3tiiENaplJ_y8X_"
|
"imM4ACRgl0Y4LqJpLFfgBhkumd4dne2P9oM6qLzMnHfspPq8AFQFHXaiSicu2gSaCwpk36ZK-WX17DaTOkYFncIKl_rSZAkb8OzTpNX0aB_590hUpAf74-"
|
||||||
"OmC8tzvKCCdXapsas3-Won2R_ryQVJlB9j1tAARpNanIEwhOf9CHmbsYM,-8tTNfrKABIfOSlCdr2ajhLqF1i4hRiM-jSzISXAEmc-Nj75Rrg*");
|
"TU368A1fgXLw2aunwn0wBNvz0ywFEiAjmD8PfgUzA6IrvkP1eoKoY4A_NNBXnirca7CjWxOoguXRGaHjzq9vrDm8ABTk2o0u29R,Nqmz_4LN1Fj9cNhtyhHTXuV6huLxmsflb_"
|
||||||
|
"6DR5B8dwk8IMYup0z5AXHhLww0BmZkDKKCWjVehxWvoHkz8FNViV9Oduwv7ZGyHUYs47HUpOIr1Wirp6LEvsxBcDBf-T_XOK945j-z_"
|
||||||
|
"MtxXiNKqtAuaL8iw7OOIpVnXqIa77yGuOFFW-u2wv1cK1M3s_OqmgEdj0JZfoYbjT6lIEVsSXKMYwwf9zkAjx23K-gqrM8c8nStv4EYT7ZU6o_"
|
||||||
|
"I0KZ6OJVnCFElYLamz82NIRiPdzyuJcPoslNCXpQV_vWlyGJ0OIoR,2MrkkwMnTNx7HR4FJ6ACh0cQZmdBEB2pM4eQSqpJEC367JtCMzM*")
|
||||||
|
<< 652;
|
||||||
}
|
}
|
||||||
|
|
||||||
void steamTicket()
|
void steamTicket()
|
||||||
{
|
{
|
||||||
QFETCH(QByteArray, ticketBytes);
|
QFETCH(QString, ticketBytes);
|
||||||
QFETCH(uint32_t, time);
|
QFETCH(uint32_t, time);
|
||||||
QFETCH(QString, encryptedTicket);
|
QFETCH(QString, encryptedTicket);
|
||||||
|
QFETCH(int, encryptedLength);
|
||||||
|
|
||||||
QCOMPARE(encryptSteamTicket(ticketBytes, time), encryptedTicket);
|
auto pair = std::pair{encryptedTicket, encryptedLength};
|
||||||
|
QCOMPARE(encryptSteamTicket(ticketBytes, time), pair);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,4 @@
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
QString encryptGameArg(const QString &arg);
|
QString encryptGameArg(const QString &arg);
|
||||||
QString encryptSteamTicket(const QByteArray &ticket, uint32_t time);
|
std::pair<QString, int> encryptSteamTicket(QString ticket, uint32_t time);
|
||||||
|
|
|
@ -16,7 +16,7 @@ public:
|
||||||
|
|
||||||
QCoro::Task<> initialize();
|
QCoro::Task<> initialize();
|
||||||
QCoro::Task<> shutdown();
|
QCoro::Task<> shutdown();
|
||||||
QCoro::Task<QString> getTicket();
|
QCoro::Task<std::pair<QString, int>> getTicket();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QNetworkAccessManager m_qnam;
|
QNetworkAccessManager m_qnam;
|
||||||
|
|
|
@ -101,13 +101,13 @@ QStringList intoChunks(const QString &str, const int maxChunkSize)
|
||||||
return chunks;
|
return chunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString encryptSteamTicket(const QByteArray &ticket, uint32_t time)
|
std::pair<QString, int> encryptSteamTicket(QString ticket, uint32_t time)
|
||||||
{
|
{
|
||||||
// Round the time down
|
// Round the time down
|
||||||
time -= 5;
|
time -= 5;
|
||||||
time -= time % 60;
|
time -= time % 60;
|
||||||
|
|
||||||
auto ticketString = QString::fromLatin1(ticket.toHex()).remove(QLatin1Char('-')).toLower();
|
auto ticketString = ticket.remove(QLatin1Char('-')).toLower();
|
||||||
auto rawTicketBytes = ticketString.toLatin1();
|
auto rawTicketBytes = ticketString.toLatin1();
|
||||||
rawTicketBytes.append('\0');
|
rawTicketBytes.append('\0');
|
||||||
|
|
||||||
|
@ -160,5 +160,8 @@ QString encryptSteamTicket(const QByteArray &ticket, uint32_t time)
|
||||||
encoded.replace('/', '_');
|
encoded.replace('/', '_');
|
||||||
encoded.replace('=', '*');
|
encoded.replace('=', '*');
|
||||||
|
|
||||||
return intoChunks(QString::fromLatin1(encoded), SPLIT_SIZE).join(QLatin1Char(','));
|
const auto parts = intoChunks(QString::fromLatin1(encoded), SPLIT_SIZE);
|
||||||
|
const auto finalString = parts.join(QLatin1Char(','));
|
||||||
|
|
||||||
|
return {finalString, finalString.length() - (parts.length() - 1)};
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,12 +232,13 @@ QCoro::Task<std::optional<SquareEnixLogin::StoredInfo>> SquareEnixLogin::getStor
|
||||||
if (m_info->profile->account()->config()->license() == Account::GameLicense::WindowsSteam) {
|
if (m_info->profile->account()->config()->license() == Account::GameLicense::WindowsSteam) {
|
||||||
query.addQueryItem(QStringLiteral("issteam"), QString::number(1));
|
query.addQueryItem(QStringLiteral("issteam"), QString::number(1));
|
||||||
|
|
||||||
|
// initialize the steam api
|
||||||
co_await m_launcher.steamApi()->initialize();
|
co_await m_launcher.steamApi()->initialize();
|
||||||
|
|
||||||
auto ticket = co_await m_launcher.steamApi()->getTicket();
|
// grab an auth ticket
|
||||||
|
auto [ticket, ticketSize] = co_await m_launcher.steamApi()->getTicket();
|
||||||
query.addQueryItem(QStringLiteral("session_ticket"), ticket);
|
query.addQueryItem(QStringLiteral("session_ticket"), ticket);
|
||||||
query.addQueryItem(QStringLiteral("ticket_size"), QString::number(ticket.length()));
|
query.addQueryItem(QStringLiteral("ticket_size"), QString::number(ticketSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl url;
|
QUrl url;
|
||||||
|
|
|
@ -34,7 +34,7 @@ QCoro::Task<> SteamAPI::shutdown()
|
||||||
Q_UNUSED(co_await m_qnam.post(QNetworkRequest(url), QByteArray{}))
|
Q_UNUSED(co_await m_qnam.post(QNetworkRequest(url), QByteArray{}))
|
||||||
}
|
}
|
||||||
|
|
||||||
QCoro::Task<QString> SteamAPI::getTicket()
|
QCoro::Task<std::pair<QString, int>> SteamAPI::getTicket()
|
||||||
{
|
{
|
||||||
QUrl url;
|
QUrl url;
|
||||||
url.setScheme(QStringLiteral("http"));
|
url.setScheme(QStringLiteral("http"));
|
||||||
|
@ -45,5 +45,7 @@ QCoro::Task<QString> SteamAPI::getTicket()
|
||||||
const auto reply = co_await m_qnam.get(QNetworkRequest(url));
|
const auto reply = co_await m_qnam.get(QNetworkRequest(url));
|
||||||
const auto ticketBytes = reply->readAll();
|
const auto ticketBytes = reply->readAll();
|
||||||
|
|
||||||
co_return encryptSteamTicket(ticketBytes, 5); // TOOD: get time
|
const QJsonDocument document = QJsonDocument::fromJson(ticketBytes);
|
||||||
|
|
||||||
|
co_return encryptSteamTicket(document[QStringLiteral("ticket")].toString(), document[QStringLiteral("ticket")].toInt());
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,13 +47,6 @@ FormCard.FormCardPage {
|
||||||
description: i18n("If the account holds multiple licenses, choose the preferred one.")
|
description: i18n("If the account holds multiple licenses, choose the preferred one.")
|
||||||
model: ["Windows", "Steam", "macOS"]
|
model: ["Windows", "Steam", "macOS"]
|
||||||
text: i18n("License")
|
text: i18n("License")
|
||||||
|
|
||||||
onCurrentIndexChanged: {
|
|
||||||
if (currentIndex === 1) {
|
|
||||||
currentIndex = 0;
|
|
||||||
errorDialog.open();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
FormCard.FormDelegateSeparator {
|
FormCard.FormDelegateSeparator {
|
||||||
above: licenseField
|
above: licenseField
|
||||||
|
@ -87,12 +80,4 @@ FormCard.FormCardPage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kirigami.PromptDialog {
|
|
||||||
id: errorDialog
|
|
||||||
|
|
||||||
showCloseButton: false
|
|
||||||
standardButtons: Kirigami.Dialog.Ok
|
|
||||||
title: i18n("Steam Warning")
|
|
||||||
subtitle: i18n("Steam linked Square Enix accounts are not currently supported. You will have to use another launcher that supports these, such as the official launcher or XIVLauncher.Core.")
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue