1.7.3 Add automatic ack on confirming Trades accordingly to new update

This commit is contained in:
achiez
2025-07-17 22:49:22 +03:00
parent 04e2188437
commit 1ad30ba49d
18 changed files with 212 additions and 64 deletions
+1
View File
@@ -21,6 +21,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "changelog", "changelog", "{
changelog\1.5.6.html = changelog\1.5.6.html
changelog\1.7.1.html = changelog\1.7.1.html
changelog\1.7.2.html = changelog\1.7.2.html
changelog\1.7.3.html = changelog\1.7.3.html
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SteamLibForked", "src\SteamLibForked\SteamLibForked.csproj", "{224F9DB0-3D20-A614-BA2A-12F22B13A2C6}"
+3 -3
View File
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>1.7.2.0</version>
<url>https://github.com/achiez/NebulaAuth-Steam-Desktop-Authenticator-by-Achies/releases/download/1.7.2/NebulaAuth.1.7.2.zip</url>
<changelog>https://achiez.github.io/NebulaAuth-Steam-Desktop-Authenticator-by-Achies/changelog/1.7.2.html</changelog>
<version>1.7.3.0</version>
<url>https://github.com/achiez/NebulaAuth-Steam-Desktop-Authenticator-by-Achies/releases/download/1.7.3/NebulaAuth.1.7.3.zip</url>
<changelog>https://achiez.github.io/NebulaAuth-Steam-Desktop-Authenticator-by-Achies/changelog/1.7.3.html</changelog>
<mandatory>false</mandatory>
</item>
+4 -4
View File
@@ -76,10 +76,10 @@
<a href="https://t.me/nebulaauth">t.me/nebulaauth</a>
</b>
</li>
<li><b>UPDATE:</b> Added support for a new confirmation type — Purchase.</li>
<li><b>UPDATE:</b> Merged Global 1.7.0 updates into the release version (<a href="https://t.me/nebulaauth/32">patch notes</a>).</li>
<li><b>FIX:</b> Fixed a crash occurring during confirmation loading.</li>
<li><b>ENHANCEMENT:</b> Improved localization and system messages.</li>
<li><b>UPDATE:</b> Added support for a new confirmation type — Purchase.</li>
<li><b>UPDATE:</b> Merged Global 1.7.0 updates into the release version (<a href="https://t.me/nebulaauth/32">patch notes</a>).</li>
<li><b>FIX:</b> Fixed a crash occurring during confirmation loading.</li>
<li><b>ENHANCEMENT:</b> Improved localization and system messages.</li>
</ul>
</div>
</div>
+1 -1
View File
@@ -76,7 +76,7 @@
<a href="https://t.me/nebulaauth">t.me/nebulaauth</a>
</b>
</li>
<li><b>FIX:</b> Crash on loading trade confirmations</li>
<li><b>FIX:</b> Crash on loading trade confirmations</li>
</ul>
</div>
</div>
+87
View File
@@ -0,0 +1,87 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Changelog</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #eeeeee;
color: #333;
line-height: 1.6;
}
.changelog-container {
background-color: #fff;
border-radius: 10px;
padding: 25px;
margin: 25px auto;
max-width: 800px;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
.change {
margin-bottom: 20px;
padding: 0;
border-left: 4px solid #a50ec7;
background-color: #f9f9f9;
}
.version {
font-weight: 600;
font-size: 1.5em;
color: #a50ec7;
margin-left: 10px;
}
.date {
font-style: italic;
color: #888;
margin-bottom: 10px;
margin-left: 15px;
}
.description {
font-size: 1em;
padding: 0 15px;
}
.description ul {
list-style: inside square;
padding: 0;
}
@media only screen and (max-width: 600px) {
.changelog-container {
width: 90%;
margin: 25px auto;
padding: 25px;
}
}
</style>
</head>
<body>
<div class="changelog-container">
<!-- Changelog entry -->
<div class="change">
<div class="version">Version 1.7.3</div>
<div class="date">17.07.2025</div>
<div class="description">
<ul>
<li>
<b>NEWS:</b> Official Telegram group now available! Join us at
<b>
<a href="https://t.me/nebulaauth">t.me/nebulaauth</a>
</b>
</li>
<li><b>UPDATE:</b> Added automatic acknowledgment request for sending trade confirmation</li>
<li><b>FIX:</b> Fixed notifications text in auto-confirm timer</li>
</ul>
</div>
</div>
</div>
</body>
</html>
+2 -6
View File
@@ -1,17 +1,13 @@
<Application x:Class="NebulaAuth.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:converters="clr-namespace:NebulaAuth.Converters"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
xmlns:background="clr-namespace:NebulaAuth.Converters.Background">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Converters/Converters.xaml"/>
<ResourceDictionary Source="/Converters/Converters.xaml" />
<ResourceDictionary Source="Theme/Themes/DefaultTheme.xaml" />
<ResourceDictionary
Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesign3.Defaults.xaml" />
+16 -2
View File
@@ -13,6 +13,7 @@ using NebulaAuth.Core;
using NebulaAuth.Model.Entities;
using NebulaAuth.Utility;
using SteamLib.Api.Mobile;
using SteamLib.Api.Trade;
using SteamLib.Authentication;
using SteamLib.Exceptions.Authorization;
using SteamLib.SteamMobile.Confirmations;
@@ -90,7 +91,7 @@ public partial class PortableMaClient : ObservableObject, IDisposable
var toConfirm = new List<Confirmation>();
if (AutoConfirmMarket)
{
var market = conf.Where(c =>
var market = conf.Where(c =>
c.ConfType is ConfirmationType.MarketSellTransaction or ConfirmationType.Purchase);
toConfirm.AddRange(market);
}
@@ -107,6 +108,7 @@ public partial class PortableMaClient : ObservableObject, IDisposable
Shell.Logger.Debug("Timer {accountName}: Sending confirmations. Count: {count}", Mafile.AccountName,
toConfirm.Count);
var success = await HandleTimerRequest(() => SendConfirmations(toConfirm));
//TODO: handle success == false
Shell.Logger.Debug("Timer {accountName}: Confirmation sent: {confirmResult}", Mafile.AccountName, success);
return toConfirm.Count;
}
@@ -126,7 +128,19 @@ public partial class PortableMaClient : ObservableObject, IDisposable
private async Task<bool> SendConfirmations(IEnumerable<Confirmation> confirmations)
{
return await SteamMobileConfirmationsApi.SendMultipleConfirmations(Client, confirmations,
var conf = confirmations.ToList();
var res = await SteamMobileConfirmationsApi.SendMultipleConfirmations(Client, conf,
Mafile.SessionData!.SteamId, Mafile, true, _cts.Token);
if (!res && conf.Any(c => c.ConfType == ConfirmationType.Trade))
{
Shell.Logger.Warn("Timer {accountName}: Failed to send trade confirmations. Sending ack",
Mafile.AccountName);
await SteamTradeApi.Acknowledge(Client, Mafile.SessionData!.SessionId, _cts.Token);
await Task.Delay(10, _cts.Token);
}
return await SteamMobileConfirmationsApi.SendMultipleConfirmations(Client, conf,
Mafile.SessionData!.SteamId, Mafile, true, _cts.Token);
}
+29 -5
View File
@@ -8,6 +8,7 @@ using AchiesUtilities.Web.Proxy;
using NebulaAuth.Model.Entities;
using SteamLib.Api.Mobile;
using SteamLib.Api.Services;
using SteamLib.Api.Trade;
using SteamLib.Authentication;
using SteamLib.Exceptions.Authorization;
using SteamLib.ProtoCore.Services;
@@ -78,26 +79,49 @@ public static class MaClient
return SessionHandler.RefreshMobileToken(new HttpClientHandlerPair(Client, ClientHandler), mafile);
}
public static Task<bool> SendConfirmation(Mafile mafile, Confirmation confirmation, bool confirm)
public static async Task<bool> SendConfirmation(Mafile mafile, Confirmation confirmation, bool confirm)
{
ValidateMafile(mafile);
SetProxy(mafile);
return SteamMobileConfirmationsApi.SendConfirmation(Client, confirmation, mafile.SessionData!.SteamId, mafile,
var res = await SteamMobileConfirmationsApi.SendConfirmation(Client, confirmation, mafile.SessionData!.SteamId,
mafile,
confirm);
if (!res && confirmation.ConfType == ConfirmationType.Trade)
{
Shell.Logger.Warn("Failed to send trade confirmation for {accountName}. Sending ack", mafile.AccountName);
await SteamTradeApi.Acknowledge(Client, mafile.SessionData.SessionId);
await Task.Delay(10);
}
return await SteamMobileConfirmationsApi.SendConfirmation(Client, confirmation, mafile.SessionData!.SteamId,
mafile,
confirm);
}
public static Task<bool> SendMultipleConfirmation(Mafile mafile, IEnumerable<Confirmation> confirmations,
public static async Task<bool> SendMultipleConfirmation(Mafile mafile, IEnumerable<Confirmation> confirmations,
bool confirm)
{
var enumerable = confirmations.ToList();
if (enumerable.Count == 0)
{
return Task.FromResult(false);
return false;
}
ValidateMafile(mafile);
SetProxy(mafile);
return SteamMobileConfirmationsApi.SendMultipleConfirmations(Client, enumerable, mafile.SessionData!.SteamId,
var res = await SteamMobileConfirmationsApi.SendMultipleConfirmations(Client, enumerable,
mafile.SessionData!.SteamId,
mafile, confirm);
if (!res && enumerable.Any(c => c.ConfType == ConfirmationType.Trade))
{
Shell.Logger.Warn("Failed to send trade confirmations for {accountName}. Sending ack", mafile.AccountName);
await SteamTradeApi.Acknowledge(Client, mafile.SessionData.SessionId);
await Task.Delay(10);
}
return await SteamMobileConfirmationsApi.SendMultipleConfirmations(Client, enumerable,
mafile.SessionData!.SteamId,
mafile, confirm);
}
+2 -2
View File
@@ -10,7 +10,7 @@
<SatelliteResourceLanguages>en;ru;ua</SatelliteResourceLanguages>
<ApplicationIcon>Theme\lock.ico</ApplicationIcon>
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>
<AssemblyVersion>1.7.2</AssemblyVersion>
<AssemblyVersion>1.7.3</AssemblyVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
@@ -36,7 +36,7 @@
<ItemGroup>
<Resource Include="Theme\Background.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<Resource Include="Theme\Background_Old.jpg">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
+2 -5
View File
@@ -1,10 +1,6 @@
Есть люди которым нужна функция просмотра и завершения сессий аккаунта. Скорее всего в следующей версии это будет реализовано
• Сейчас, при наличии новой версии, отображается стандартное окно обновлений из библиотеки. Планируется сделать кастомный дизайн, для соответствия общему стилю.
Сейчас, при наличии новой версии, отображается стандартное окно обновлений из библиотеки. Планируется сделать кастомный дизайн, для соответствия общему стилю.
• В приложении реализованы "совмещённые" подтверждения для торговой площадки. Т.е. при наличии более одного предмета, ожидающего подтверждение, можно либо отменить, либо подтвердить все. В планах добавить расширенный функционал, с возможностью точечного управления.
• Добавить кнопку "открыть мафайл" в меню "Файл" по аналогии с открытием папки
• Ускорить появление подсказок в интерфейсе
• Добавить запоминание пароля при привязке мафайла
• Функция переноса гуарда с мобильного устройства на ПК с созданием мафайла
• Добавить полное шифрование мафайлов по аналогии с SDA
• Сделать автоматический билд и загрузку обновления на Github при изменении в мастер ветке
• Антик-окно как в MarketApp, возможность сразу открыть браузер напр. на CefSharp с залогиненым аккаунтом
@@ -12,3 +8,4 @@
• Безопасное сохранение мафайлов через .tmp / .bak
• Создание механизма накопления ошибок, чтобы исправить Patch Tuesday, условно аккаунт может игнорировать ошибки 1-2 часа (настриавемо)
• Исправить "Перенос гуарда". Иногда не хочет принимать код / подтверждение
@@ -7,7 +7,7 @@
xmlns:entities="clr-namespace:NebulaAuth.Model.Entities"
xmlns:vm="clr-namespace:NebulaAuth.ViewModel">
<DataTemplate DataType="{x:Type confirmations:Confirmation}">
<Grid>
<Grid.ColumnDefinitions>
+30 -30
View File
@@ -260,7 +260,7 @@
"en": "Purchase",
"ru": "Покупка",
"ua": "Покупка"
}
}
},
"CodeCopied": {
"ru": "Скопировано",
@@ -1286,36 +1286,36 @@
"ru": "Ошибка SMS-кода, попробуйте еще раз",
"ua": "Помилка SMS-коду, спробуйте ще раз"
}
}
},
"MAAC": {
"TimerConfirmed": {
"ru": "Авто: подтверждено ",
"en": "Auto: confirmed ",
"ua": "Авто: підтверджено "
},
"TimerNotConfirmed": {
"ru": "Авто: подтверждение не сработало",
"en": "Auto: confirmation was unsuccessful",
"ua": "Авто: підтвердження не спрацювало"
},
"TimerSessionError": {
"ru": "необходимо обновить сессию или перелогиниться",
"en": "need to refresh session or relogin",
"ua": "необхідно оновити сесію або перелогінитися"
},
"TimerPrefix": {
"ru": "Авто ",
"en": "Auto ",
"ua": "Авто "
},
"TimerPreventedOverlap": {
"ru":
"Авто: таймер подтверждений пытался начать новый цикл, когда предыдущий еще не завершился. Советуем увеличить задержку",
"en":
"Auto: confirmation timer tried to start new cycle when previous one was not finished yet. We recommend to increase delay",
"ua":
"Авто: таймер підтверджень намагався запустити новий цикл, коли попередній ще не закінчився. Рекомендуємо збільшити затримку"
"MAAC": {
"TimerConfirmed": {
"ru": "Авто: подтверждено ",
"en": "Auto: confirmed ",
"ua": "Авто: підтверджено "
},
"TimerNotConfirmed": {
"ru": "Авто: подтверждение не сработало",
"en": "Auto: confirmation was unsuccessful",
"ua": "Авто: підтвердження не спрацювало"
},
"TimerSessionError": {
"ru": "необходимо обновить сессию или перелогиниться",
"en": "need to refresh session or relogin",
"ua": "необхідно оновити сесію або перелогінитися"
},
"TimerPrefix": {
"ru": "Авто ",
"en": "Auto ",
"ua": "Авто "
},
"TimerPreventedOverlap": {
"ru":
"Авто: таймер подтверждений пытался начать новый цикл, когда предыдущий еще не завершился. Советуем увеличить задержку",
"en":
"Auto: confirmation timer tried to start new cycle when previous one was not finished yet. We recommend to increase delay",
"ua":
"Авто: таймер підтверджень намагався запустити новий цикл, коли попередній ще не закінчився. Рекомендуємо збільшити затримку"
}
}
},
"CantAlignTimeError": {
@@ -72,8 +72,8 @@ public static class SteamMobileConfirmationsApi
var op = confirm ? "allow" : "cancel";
var query = GetConfirmationKvp(steamId, data.DeviceId, data.IdentitySecret, op).ToList();
query.Insert(0, new KeyValuePair<string, string>("op", op));
foreach (var confirmation in confirmations)
var list = confirmations.ToList();
foreach (var confirmation in list)
{
query.Add(new KeyValuePair<string, string>("cid[]", confirmation.Id.ToString()));
query.Add(new KeyValuePair<string, string>("ck[]", confirmation.Nonce.ToString()));
@@ -0,0 +1,27 @@
using SteamLib.Core;
namespace SteamLib.Api.Trade;
public static class SteamTradeApi
{
public static async Task<bool> Acknowledge(HttpClient client, string sessionId,
CancellationToken cancellationToken = default)
{
var data = new Dictionary<string, string>
{
{"sessionid", sessionId},
{"message", "1"}
};
var req = new HttpRequestMessage(HttpMethod.Post, Routes.ACKNOWLEDGE);
req.Content = new FormUrlEncodedContent(data);
var resp = await client.SendAsync(req, cancellationToken);
var cont = await resp.EnsureSuccessStatusCode().Content.ReadAsStringAsync(cancellationToken);
return cont == "[]";
//{"success":false} - unauthenticated
}
public static class Routes
{
public const string ACKNOWLEDGE = SteamConstants.STEAM_COMMUNITY + "//trade/new/acknowledge"; //Not a typo
}
}
@@ -21,7 +21,7 @@ public class SessionData : ISessionData
public SteamAuthToken RefreshToken { get; }
public ConcurrentDictionary<SteamDomain, SteamAuthToken> Tokens { get; }
[JsonConstructor]
public SessionData(string sessionId, SteamId steamId, SteamAuthToken refreshToken,
IDictionary<SteamDomain, SteamAuthToken>? tokens)
@@ -2,7 +2,8 @@
public class PurchaseConfirmation : Confirmation
{
public PurchaseConfirmation(long id, ulong nonce, int intType, ulong creatorId, string typeName) : base(id, nonce, intType, creatorId, ConfirmationType.Purchase, typeName)
public PurchaseConfirmation(long id, ulong nonce, ulong creatorId, string typeName) : base(id, nonce, 12, creatorId,
ConfirmationType.Purchase, typeName)
{
}
}
+1
View File
@@ -33,6 +33,7 @@ public static class ClientBuilder
{
container.SetSteamMobileCookiesWithMobileToken(sessionData);
}
//Nebula tweak:
handler.CookieContainer.InjectWebTradeEligibilityCookie();
ConfigureCommon(handler, client);
@@ -170,7 +170,7 @@ public static class MobileConfirmationScrapper
private static PurchaseConfirmation GetPurchaseConfirmation(ConfirmationJson confirmation)
{
return new PurchaseConfirmation(confirmation.Id, confirmation.Nonce, (int) confirmation.Type,
return new PurchaseConfirmation(confirmation.Id, confirmation.Nonce,
confirmation.CreatorId, confirmation.TypeName)
{
Time = confirmation.CreationTime.ToLocalDateTime()