mirror of
https://github.com/achiez/NebulaAuth-Steam-Desktop-Authenticator-by-Achies.git
synced 2026-07-25 06:14:31 +00:00
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:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
• Есть люди которым нужна функция просмотра и завершения сессий аккаунта. Скорее всего в следующей версии это будет реализовано
|
||||
• Сейчас, при наличии новой версии, отображается стандартное окно обновлений из библиотеки. Планируется сделать кастомный дизайн, для соответствия общему стилю.
|
||||
• В приложении реализованы "совмещённые" подтверждения для торговой площадки. Т.е. при наличии более одного предмета, ожидающего подтверждение, можно либо отменить, либо подтвердить все. В планах добавить расширенный функционал, с возможностью точечного управления.
|
||||
• Добавить кнопку "открыть мафайл" в меню "Файл" по аналогии с открытием папки
|
||||
• Ускорить появление подсказок в интерфейсе
|
||||
• Добавить запоминание пароля при привязке мафайла
|
||||
• Функция переноса гуарда с мобильного устройства на ПК с созданием мафайла
|
||||
• Добавить полное шифрование мафайлов по аналогии с SDA
|
||||
• Сделать автоматический билд и загрузку обновления на Github при изменении в мастер ветке
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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": "Мафайл скопирован",
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user