1
Fork 0
mirror of https://github.com/redstrate/Astra.git synced 2025-05-17 06:37: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:
Joshua Goins 2025-05-04 16:33:07 -04:00
parent 3d39887d9c
commit 05d33dc5d7
8 changed files with 39 additions and 43 deletions

View file

@ -15,8 +15,6 @@ plugins!
* 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.
**Note:** Steam-linked Square Enix accounts are not currently supported. You will have to use the official launcher or XIVLauncher.Core.
## Get It
Details on where to find stable releases of Astra can be found on its [homepage](https://xiv.zone/astra/install).

View file

@ -12,30 +12,37 @@ class EncryptedArgTest : public QObject
private Q_SLOTS:
void steamTicket_data()
{
QTest::addColumn<QByteArray>("ticketBytes");
QTest::addColumn<QString>("ticketBytes");
QTest::addColumn<uint32_t>("time");
QTest::addColumn<QString>("encryptedTicket");
QTest::addColumn<int>("encryptedLength");
QTest::addRow("test 1") << QByteArrayLiteral(
"caf59103e80d600b4a9233358c131a437cedcf8802eb705223cce84278e6cb4c3655a7accd98097c06748b33d340f9de79920754616e295b88b833d9d84412ffc6a4406c60a6691ce5"
"2c27b5b1c90d36a6a810cef4c81fdc3c75aaa87353433f2f3c7232c00d1198a79bb27df6edb89c5fd0a3a11e957c40")
<< static_cast<uint32_t>(1746386404)
<< QStringLiteral(
"jX6TeGNIJFgecYIQU4YLSnhkbCpTihoIBB6Dw5iw7rAWQiULVB-NhOsfJwLh7EHW5wYwU1XRJAy5dw6JCWQ6v0R5SwP_84DIVDT5gfET_"
"BoXmUr7rfXtJF62vpZ16XfwH2-P2KlaVRTaSYQ8xqTqC_fef6agOdYHvL_g-cNyjjv3xTMsekWnDCDhdG3Y1NvnPcXdAX9v0pjHUu5W5-"
"k8iZhUeTcTjYhMODBPNXz6uf7mKd1wkwAsTnDZoL89k8U1asq78hyaiWsFb4Nb39vK0n0TZfb20yFoXZh9NRO2VpgS,dSTy86oaqm2ZjKu7FnnHmFU6R_"
"lS8pk8EB6itIekPAfC37LYSBIEI1rT9cEvoXNkX6hIGnZ5sthiNPoi5nx9_HdjWYQ9R0Kar-Bgjeu77Av753T0GpVhJhYFyBkMe-"
"NAqGMEjkYFjRUwOX9pEJGEszEL3_mWEbryQ8wL4ZaYk5xu4HAXe5hRwk-JUv__BW8IpiR_OsphQUgeKtRmXUPw1eIU2NYdsd3AJLAP3tiiENaplJ_y8X_"
"OmC8tzvKCCdXapsas3-Won2R_ryQVJlB9j1tAARpNanIEwhOf9CHmbsYM,-8tTNfrKABIfOSlCdr2ajhLqF1i4hRiM-jSzISXAEmc-Nj75Rrg*");
QTest::addRow("real ticket")
<< QStringLiteral(
"140000009efb2c79d200f07599f633050100100195c517681800000001000000020000002c9ea991afec1a49f7e72d000b000000b8000000380000000400000099f63305010"
"010012a990000c47323496501a8c000000000807a1268002a2e680100908400000100c5000400000000004e408e518c259b8b329b5fcfdb00903fadad36d7e088813dc9b174"
"b06e08b69f8f46d083cf4118d1eb4062e009147906d9c80759af3eb221f7fbb8e28d402e11ba80e3cf4a101487f87ccce9688daf99dd412e6bcaab6e58f70030ff99323e4c8"
"1824659f7aa89188fadc6402bcb540843e1578cd112d4536fd65c4bd926f754")
<< static_cast<uint32_t>(1746389891)
<< QStringLiteral(
"Tjr8Lv1O0HjJ7U4dOfkA9BdLAnEaCl_TU0GnYGGLTBM06TV9Ggf-fYb7WMqD-Xv758Q1zzSPTeaJctl8au-"
"imM4ACRgl0Y4LqJpLFfgBhkumd4dne2P9oM6qLzMnHfspPq8AFQFHXaiSicu2gSaCwpk36ZK-WX17DaTOkYFncIKl_rSZAkb8OzTpNX0aB_590hUpAf74-"
"TU368A1fgXLw2aunwn0wBNvz0ywFEiAjmD8PfgUzA6IrvkP1eoKoY4A_NNBXnirca7CjWxOoguXRGaHjzq9vrDm8ABTk2o0u29R,Nqmz_4LN1Fj9cNhtyhHTXuV6huLxmsflb_"
"6DR5B8dwk8IMYup0z5AXHhLww0BmZkDKKCWjVehxWvoHkz8FNViV9Oduwv7ZGyHUYs47HUpOIr1Wirp6LEvsxBcDBf-T_XOK945j-z_"
"MtxXiNKqtAuaL8iw7OOIpVnXqIa77yGuOFFW-u2wv1cK1M3s_OqmgEdj0JZfoYbjT6lIEVsSXKMYwwf9zkAjx23K-gqrM8c8nStv4EYT7ZU6o_"
"I0KZ6OJVnCFElYLamz82NIRiPdzyuJcPoslNCXpQV_vWlyGJ0OIoR,2MrkkwMnTNx7HR4FJ6ACh0cQZmdBEB2pM4eQSqpJEC367JtCMzM*")
<< 652;
}
void steamTicket()
{
QFETCH(QByteArray, ticketBytes);
QFETCH(QString, ticketBytes);
QFETCH(uint32_t, time);
QFETCH(QString, encryptedTicket);
QFETCH(int, encryptedLength);
QCOMPARE(encryptSteamTicket(ticketBytes, time), encryptedTicket);
auto pair = std::pair{encryptedTicket, encryptedLength};
QCOMPARE(encryptSteamTicket(ticketBytes, time), pair);
}
};

View file

@ -6,4 +6,4 @@
#include <QString>
QString encryptGameArg(const QString &arg);
QString encryptSteamTicket(const QByteArray &ticket, uint32_t time);
std::pair<QString, int> encryptSteamTicket(QString ticket, uint32_t time);

View file

@ -16,7 +16,7 @@ public:
QCoro::Task<> initialize();
QCoro::Task<> shutdown();
QCoro::Task<QString> getTicket();
QCoro::Task<std::pair<QString, int>> getTicket();
private:
QNetworkAccessManager m_qnam;

View file

@ -101,13 +101,13 @@ QStringList intoChunks(const QString &str, const int maxChunkSize)
return chunks;
}
QString encryptSteamTicket(const QByteArray &ticket, uint32_t time)
std::pair<QString, int> encryptSteamTicket(QString ticket, uint32_t time)
{
// Round the time down
time -= 5;
time -= time % 60;
auto ticketString = QString::fromLatin1(ticket.toHex()).remove(QLatin1Char('-')).toLower();
auto ticketString = ticket.remove(QLatin1Char('-')).toLower();
auto rawTicketBytes = ticketString.toLatin1();
rawTicketBytes.append('\0');
@ -160,5 +160,8 @@ QString encryptSteamTicket(const QByteArray &ticket, uint32_t time)
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)};
}

View file

@ -232,12 +232,13 @@ QCoro::Task<std::optional<SquareEnixLogin::StoredInfo>> SquareEnixLogin::getStor
if (m_info->profile->account()->config()->license() == Account::GameLicense::WindowsSteam) {
query.addQueryItem(QStringLiteral("issteam"), QString::number(1));
// initialize the steam api
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("ticket_size"), QString::number(ticket.length()));
query.addQueryItem(QStringLiteral("ticket_size"), QString::number(ticketSize));
}
QUrl url;

View file

@ -34,7 +34,7 @@ QCoro::Task<> SteamAPI::shutdown()
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;
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 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());
}

View file

@ -47,13 +47,6 @@ FormCard.FormCardPage {
description: i18n("If the account holds multiple licenses, choose the preferred one.")
model: ["Windows", "Steam", "macOS"]
text: i18n("License")
onCurrentIndexChanged: {
if (currentIndex === 1) {
currentIndex = 0;
errorDialog.open();
}
}
}
FormCard.FormDelegateSeparator {
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.")
}
}