1.5.4 prepared for release

- Compatibility update is completed
- Added 'Copy SteamId' menu item in context menu of mafile
- Proxy and password automatically saved in mafile after linking
- SetCryptPasswordDialog now supports "Enter" hot-key
- Loc updates
- Added PlannedChanges.txt
- Added ClipboardHelper.cs to improved code readability
This commit is contained in:
Давид Чернопятов
2024-11-10 14:42:49 +02:00
parent ef8e12e20d
commit c705caac8f
14 changed files with 183 additions and 83 deletions
+1
View File
@@ -201,6 +201,7 @@
<FrameworkElement.ContextMenu>
<ContextMenu>
<MenuItem InputGestureText="Ctrl+C" Header="{Tr MainWindow.ContextMenus.Mafile.CopyLogin}" Command="{Binding CopyLoginCommand}" CommandParameter="{Binding PlacementTarget.SelectedValue, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
<MenuItem Header="{Tr MainWindow.ContextMenus.Mafile.CopySteamId}" Command="{Binding CopySteamIdCommand}" CommandParameter="{Binding PlacementTarget.SelectedValue, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
<MenuItem InputGestureText="Ctrl+X" Header="{Tr MainWindow.ContextMenus.Mafile.CopyMafile}" Command="{Binding CopyMafileCommand}" CommandParameter="{Binding PlacementTarget.SelectedValue, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
<MenuItem Header="{Tr MainWindow.ContextMenus.Mafile.AddToGroup}" ItemsSource="{Binding Groups}">
<ItemsControl.ItemContainerStyle>
@@ -0,0 +1,15 @@
using System;
using NebulaAuth.Model.Entities;
using SteamLib;
namespace NebulaAuth.Model.Exceptions;
public class MafileNeedReloginException : Exception
{
public Mafile Mafile { get; }
public MafileNeedReloginException(Mafile mafile)
{
Mafile = mafile;
}
}
+9 -2
View File
@@ -4,6 +4,7 @@ using SteamLib;
using SteamLib.Utility.MafileSerialization;
using System.Collections.Generic;
using System;
using NebulaAuth.Model.Exceptions;
using Newtonsoft.Json;
namespace NebulaAuth.Model;
@@ -20,7 +21,7 @@ public static class NebulaSerializer
{
AllowDeviceIdGeneration = true,
AllowSessionIdGeneration = true,
ThrowIfInvalidSteamId = true
ThrowIfInvalidSteamId = false
}
});
}
@@ -39,7 +40,13 @@ public static class NebulaSerializer
var proxy = GetPropertyValue<MaProxy>("Proxy", props);
var group = GetPropertyValue<string>("Group", props);
var password = GetPropertyValue<string>("Password", props);
return Mafile.FromMobileDataExtended((MobileDataExtended)mobileData, proxy, group, password);
var mafile = Mafile.FromMobileDataExtended((MobileDataExtended)mobileData, proxy, group, password);
if (!info.SteamIdValid)
throw new MafileNeedReloginException(mafile);
return mafile;
}
private static T? GetPropertyValue<T>(string name, Dictionary<string, JProperty> dictionary)
+11 -7
View File
@@ -8,6 +8,8 @@ using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using AchiesUtilities.Extensions;
using NebulaAuth.Model.Exceptions;
using NLog.Targets;
using SteamLib;
namespace NebulaAuth.Model;
@@ -66,7 +68,14 @@ public static class Storage
MaFiles = new ObservableCollection<Mafile>(MaFiles.OrderBy(m => m.AccountName));
}
/// <summary>
///
/// </summary>
/// <param name="path"></param>
/// <param name="overwrite"></param>
/// <exception cref="FormatException"></exception>
/// <exception cref="SessionInvalidException"></exception>
/// <exception cref="IOException"></exception>
public static void AddNewMafile(string path, bool overwrite)
{
Mafile data;
@@ -74,17 +83,12 @@ public static class Storage
{
data = ReadMafile(path);
}
catch (ArgumentException ex)
when(ex.ParamName == nameof(MobileDataExtended.SteamId))
{
throw new SessionInvalidException(); //Allows to handle LoginOnImport
}
catch (Exception ex)
when(ex is not MafileNeedReloginException)
{
Shell.Logger.Warn(ex, "Can't load mafile");
throw new FormatException("File data is not valid", ex);
}
if (string.IsNullOrWhiteSpace(data.AccountName))
throw new FormatException("File data is not valid. Missing AccountName");
+1 -6
View File
@@ -10,7 +10,7 @@
<SatelliteResourceLanguages>en;ru;ua</SatelliteResourceLanguages>
<ApplicationIcon>Theme\lock.ico</ApplicationIcon>
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>
<AssemblyVersion>1.5.3</AssemblyVersion>
<AssemblyVersion>1.5.4</AssemblyVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
@@ -42,11 +42,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Model\Exceptions\" />
<Folder Include="Utility\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SteamLibForked\SteamLibForked.csproj" />
</ItemGroup>
+9
View File
@@ -0,0 +1,9 @@
• Есть люди которым нужна функция просмотра и завершения сессий аккаунта. Скорее всего в следующей версии это будет реализовано
• Сейчас, при наличии новой версии, отображается стандартное окно обновлений из библиотеки. Планируется сделать кастомный дизайн, для соответствия общему стилю.
• В приложении реализованы "совмещённые" подтверждения для торговой площадки. Т.е. при наличии более одного предмета, ожидающего подтверждение, можно либо отменить, либо подтвердить все. В планах добавить расширенный функционал, с возможностью точечного управления.
• Добавить кнопку "открыть мафайл" в меню "Файл" по аналогии с открытием папки
• Ускорить появление подсказок в интерфейсе
• Добавить запоминание пароля при привязке мафайла
• Функция переноса гуарда с мобильного устройства на ПК с созданием мафайла
• Добавить полное шифрование мафайлов по аналогии с SDA
• Сделать автоматический билд и загрузку обновления на Github при изменении в мастер ветке
+60
View File
@@ -0,0 +1,60 @@
using NebulaAuth.Core;
using NebulaAuth.Model;
using System;
using System.Collections.Specialized;
using System.Windows;
namespace NebulaAuth.Utility;
public class ClipboardHelper
{
public static bool Set(string text)
{
var i = 0;
while (i < 20)
{
try
{
Clipboard.SetText(text);
return true;
}
catch (Exception ex)
{
if (i == 19)
{
Shell.Logger.Error(ex);
SnackbarController.SendSnackbar(LocManager.GetCommonOrDefault("Error", "Error"));
}
}
i++;
}
return false;
}
public static bool SetFiles(StringCollection files)
{
var i = 0;
while (i < 20)
{
try
{
Clipboard.SetFileDropList(files);
return true;
}
catch (Exception ex)
{
if (i == 19)
{
Shell.Logger.Error(ex);
SnackbarController.SendSnackbar(LocManager.GetCommonOrDefault("Error", "Error"));
}
}
i++;
}
return false;
}
}
@@ -19,13 +19,13 @@
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock IsHitTestVisible="False" TextWrapping="Wrap" FontWeight="Normal" Text="{Tr SetEncryptedPasswordDialog.DialogText}" theme:FontScaleWindow.Scale="0.8" theme:FontScaleWindow.ResizeFont="True" Margin="10,0,0,0" HorizontalAlignment="Left"/>
<PasswordBox FontSize="16" materialDesign:PasswordBoxAssist.Password="{Binding Password}" Margin="10" Grid.Row="1" Style="{StaticResource MaterialDesignFloatingHintRevealPasswordBox}" materialDesign:HintAssist.Hint="{Tr SetEncryptedPasswordDialog.Password}" />
<PasswordBox FontSize="16" materialDesign:PasswordBoxAssist.Password="{Binding Password, UpdateSourceTrigger=PropertyChanged}" Margin="10" Grid.Row="1" Style="{StaticResource MaterialDesignFloatingHintRevealPasswordBox}" materialDesign:HintAssist.Hint="{Tr SetEncryptedPasswordDialog.Password}" />
<Grid Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Margin="10,5,5,5" Style="{StaticResource MaterialDesignOutlinedButton}" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{StaticResource True}" Content="{Tr SetEncryptedPasswordDialog.Ok}"/>
<Button IsDefault="True" Margin="10,5,5,5" Style="{StaticResource MaterialDesignOutlinedButton}" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{StaticResource True}" Content="{Tr SetEncryptedPasswordDialog.Ok}"/>
<Button IsCancel="True" Grid.Column="1" Margin="5,5,10,5" Style="{StaticResource MaterialDesignOutlinedButton}" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{StaticResource False}" Content="{Tr SetEncryptedPasswordDialog.Cancel}"/>
</Grid>
</Grid>
+13 -45
View File
@@ -14,6 +14,7 @@ using System.Threading.Tasks;
using System.Windows;
using AchiesUtilities.Extensions;
using NebulaAuth.Model.Entities;
using NebulaAuth.Model.Exceptions;
using SteamLib.Exceptions;
using NebulaAuth.Utility;
using NebulaAuth.View.Dialogs;
@@ -99,11 +100,11 @@ public partial class MainVM //File //TODO: Refactor
notAdded++;
}
}
catch (SessionInvalidException ex)
catch (MafileNeedReloginException ex)
{
if (path.Length == 1 && ex.Data.Contains("mafile"))
if (path.Length == 1 && ex.Mafile != null)
{
var mafile = (Mafile)ex.Data["mafile"]!;
var mafile = ex.Mafile;
if (await HandleAddMafileWithoutSession(mafile))
{
added++;
@@ -243,58 +244,25 @@ public partial class MainVM //File //TODO: Refactor
private void CopyLogin(object? mafile)
{
if(mafile is not Mafile maf) return;
var i = 0;
while (i < 20)
{
try
{
Clipboard.SetText(maf.AccountName);
if(ClipboardHelper.Set(maf.AccountName))
SnackbarController.SendSnackbar(GetLocalization("LoginCopied"));
return;
}
catch (Exception ex)
{
if (i == 19)
{
Shell.Logger.Error(ex);
SnackbarController.SendSnackbar(LocManager.GetCommonOrDefault("Error", "Error"));
}
}
i++;
}
[RelayCommand]
private void CopySteamId(object? mafile)
{
if (mafile is not Mafile maf) return;
if(ClipboardHelper.Set(maf.SteamId.ToString()))
SnackbarController.SendSnackbar(GetLocalization("SteamIdCopied"));
}
[RelayCommand]
private void CopyMafile(object? mafile)
{
if (mafile is not Mafile maf) return;
var i = 0;
var path = Storage.TryFindMafilePath(maf);
if (path == null)
{
SnackbarController.SendSnackbar(GetLocalization("MafileNotCopied"));
return;
}
while (i < 20)
{
try
{
Clipboard.SetFileDropList([path]);
if(ClipboardHelper.SetFiles([path]))
SnackbarController.SendSnackbar(GetLocalization("MafileCopied"));
return;
}
catch (Exception ex)
{
if (i == 19)
{
Shell.Logger.Error(ex);
SnackbarController.SendSnackbar(LocManager.GetCommonOrDefault("Error", "Error"));
}
}
i++;
}
}
}
@@ -63,6 +63,8 @@ public partial class LinkAccountVM : ObservableObject, IEmailProvider, IPhoneNum
private bool _isLinkStarted;
private string _rCode = string.Empty;
private string _password = string.Empty;
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(ProceedCommand))]
private bool _canProceed = true;
@@ -136,6 +138,7 @@ public partial class LinkAccountVM : ObservableObject, IEmailProvider, IPhoneNum
IsLogin = true;
var userName = FieldText;
var pass = PassFieldText;
_password = pass;
FieldText = string.Empty;
IsFieldVisible = false;
HintText = string.Empty;
@@ -192,6 +195,18 @@ public partial class LinkAccountVM : ObservableObject, IEmailProvider, IPhoneNum
IsLinkCode = true;
IsCompleted = true;
var mafile = Mafile.FromMobileDataExtended(result);
try
{
if (SelectedProxy.HasValue)
mafile.Proxy = new MaProxy(SelectedProxy.Value.Key, SelectedProxy.Value.Value);
if (Settings.Instance.IsPasswordSet)
mafile.Password = PHandler.Encrypt(_password);
}
catch (Exception ex)
{
Logger.Error(ex, "Error during saving Nebula data to mafile");
}
Storage.SaveMafile(mafile);
File.Delete(Path.Combine("mafiles_backup", mafile.AccountName + ".mafile"));
HintText =
@@ -320,6 +335,7 @@ public partial class LinkAccountVM : ObservableObject, IEmailProvider, IPhoneNum
CanProceed = true;
_emailCodeTcs = new TaskCompletionSource<string>();
_rCode = string.Empty;
_password = string.Empty;
}
private void Backup(MobileDataExtended data)
+13 -3
View File
@@ -269,6 +269,11 @@
"ru": "Скопировать мафайл",
"ua": "Скопіювати мафайл"
},
"CopySteamId": {
"en": "Copy SteamID",
"ru": "Скопировать SteamID",
"ua": "Скопіювати SteamID"
},
"AddToGroup": {
"en": "Add to group",
"ru": "Добавить в группу",
@@ -620,9 +625,9 @@
"ua": "помилки:"
},
"RemoveMafileConfirmation": {
"ru": "Удалить мафайл? Это действие переместит мафайл в папку 'mafiles_removed' (Это действие не удаляет Steam Guard с аккаунта)",
"en": "Remove mafile? This action will move mafile to 'mafiles_removed' (This action does not remove the Steam Guard from the account)",
"ua": "Видалити мафайл? Ця дія перемістить мафайл у каталог 'mafiles_removed' (Ця дія не видаляє автентифікатор з облікового запису)"
"ru": "Удалить мафайл? Мафайл будет перемещен в папку 'mafiles_removed' (Это действие не удаляет Steam Guard с аккаунта)",
"en": "Remove mafile? Mafile will be moved to 'mafiles_removed' directory (This action does not remove the Steam Guard from the account)",
"ua": "Видалити мафайл? Мафайл буде переміщено у каталог 'mafiles_removed' (Ця дія не видаляє автентифікатор з облікового запису)"
},
"CantRemoveAlreadyExist": {
"ru": "Не удалось переместить мафайл, возможно в папке уже существует мафайл с таким именем.",
@@ -659,6 +664,11 @@
"ru": "Логин скопирован",
"ua": "Логін скопійовано"
},
"SteamIdCopied": {
"en": "SteamID copied",
"ru": "SteamID скопирован",
"ua": "SteamID скопійовано"
},
"MafileCopied": {
"en": "Mafile copied",
"ru": "Мафайл скопирован",
+3 -3
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>1.5.3.0</version>
<url>https://github.com/achiez/NebulaAuth-Steam-Desktop-Authenticator-by-Achies/releases/download/1.5.3/NebulaAuth.1.5.3.zip</url>
<changelog>https://achiez.github.io/NebulaAuth-Steam-Desktop-Authenticator-by-Achies/changelog/1.5.3.html</changelog>
<version>1.5.4.0</version>
<url>https://github.com/achiez/NebulaAuth-Steam-Desktop-Authenticator-by-Achies/releases/download/1.5.4/NebulaAuth.1.5.4.zip</url>
<changelog>https://achiez.github.io/NebulaAuth-Steam-Desktop-Authenticator-by-Achies/changelog/1.5.4.html</changelog>
<mandatory>false</mandatory>
</item>
@@ -75,16 +75,19 @@ public class DeserializedMafileInfo
public bool HasMissingImportantProperties => MissingImportantProperties is { Count: > 0 };
public bool HasSession => SessionResult == DeserializedMafileSessionResult.Valid;
public bool HasIdentificationProperty { get; init; }
public bool SteamIdValid { get; init; }
internal static DeserializedMafileInfo Create(MobileData mobileData, int? version = null, Dictionary<string, JProperty>? unusedProperties = null, HashSet<string>? missingProperties = null,
DeserializedMafileSessionResult sessionResult = DeserializedMafileSessionResult.Missing)
{
HashSet<string>? missingImportantProperties = null;
var hasIdentificationProperty = false;
var steamIdValid = false;
var isExtended = false;
if (mobileData is MobileDataExtended ext)
{
hasIdentificationProperty = !string.IsNullOrWhiteSpace(ext.AccountName) || ext.SteamId.Steam64.Id > SteamId64.SEED;
steamIdValid = ext.SteamId.Steam64.Id > SteamId64.SEED;
hasIdentificationProperty = !string.IsNullOrWhiteSpace(ext.AccountName) || steamIdValid;
isExtended = true;
}
@@ -104,7 +107,8 @@ public class DeserializedMafileInfo
MissingProperties = missingProperties,
UnusedProperties = unusedProperties,
SessionResult = sessionResult,
HasIdentificationProperty = hasIdentificationProperty
HasIdentificationProperty = hasIdentificationProperty,
SteamIdValid = steamIdValid
};
}
+15 -4
View File
@@ -67,11 +67,22 @@
<!-- Changelog entry -->
<div class="change">
<div class="version">Version 1.5.4</div>
<div class="date">DATE</div>
<div class="date">10.11.2024</div>
<div class="description">
- <b>NEWS:</b> Official Telegram group now available! Join us at <b><a href="https://t.me/nebulaauth">t.me/nebulaauth</a></b> <br />
- <b>FIX:</b> TEMPORARY: Added workaround for old mafiles in MafileSerializer <br />
<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>Compatibility:</b> Improved mafiles compatibility:
<ul style="margin-left: 15px">
<li>Full: with SDA, MarketApp, SIH</li>
<li>Re-login after import: LZT, TO SDA, old mafiles</li>
<li>Re-login <b>on</b> import: Mafiles without "Session" data or "SteamId" property</li>
</ul>
</li>
<li><b>UPDATE:</b> Proxy and password (if set) now automatically saved in mafile after linking guard</li>
<li><b>UI:</b> Encryption password dialog on startup now supports "Enter" hot-key</li>
<li><b>UI:</b> Added "Copy SteamId" button in the maFile context menu.</li>
</ul>
</div>
</div>
</div>