diff --git a/NebulaAuth.LegacyConverter/Program.cs b/NebulaAuth.LegacyConverter/Program.cs index c45f9e0..5e72683 100644 --- a/NebulaAuth.LegacyConverter/Program.cs +++ b/NebulaAuth.LegacyConverter/Program.cs @@ -1,10 +1,20 @@ using AchiesUtilities.Extensions; using NebulaAuth.LegacyConverter; using Newtonsoft.Json; -using SteamLib.Utility.MaFiles; +using SteamLib.Utility.MafileSerialization; + + try { + var mafileSerializer = new MafileSerializer(new MafileSerializerSettings + { + DeserializationOptions = + { + AllowDeviceIdGeneration = true, + AllowSessionIdGeneration = true, + } + }); var currentPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); if (currentPath != null) Environment.CurrentDirectory = currentPath; @@ -29,7 +39,7 @@ try } } } - + var decryptMode = false; while (true) { @@ -120,7 +130,8 @@ try } } - var maf = MafileSerializer.Deserialize(text, true, out _); + var data = mafileSerializer.Deserialize(text); + var maf = data.Data; var legacy = MafileSerializer.SerializeLegacy(maf, Formatting.Indented); var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path); Write(legacy, fileNameWithoutExtension); diff --git a/NebulaAuth.sln b/NebulaAuth.sln index 3b17041..29f7e9e 100644 --- a/NebulaAuth.sln +++ b/NebulaAuth.sln @@ -25,6 +25,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "changelog", "changelog", "{ changelog\1.5.1.html = changelog\1.5.1.html changelog\1.5.2.html = changelog\1.5.2.html changelog\1.5.3.html = changelog\1.5.3.html + changelog\1.5.4.html = changelog\1.5.4.html EndProjectSection EndProject Global diff --git a/NebulaAuth/MainWindow.xaml b/NebulaAuth/MainWindow.xaml index fac5855..fbe2140 100644 --- a/NebulaAuth/MainWindow.xaml +++ b/NebulaAuth/MainWindow.xaml @@ -201,6 +201,7 @@ + diff --git a/NebulaAuth/Model/Entities/Mafile.cs b/NebulaAuth/Model/Entities/Mafile.cs index abc8a61..f869ca9 100644 --- a/NebulaAuth/Model/Entities/Mafile.cs +++ b/NebulaAuth/Model/Entities/Mafile.cs @@ -45,6 +45,7 @@ public partial class Mafile : MobileDataExtended ServerTime = data.ServerTime, TokenGid = data.TokenGid, Uri = data.Uri, + SteamId = data.SteamId }; } public static Mafile FromMobileDataExtended(MobileDataExtended data, MaProxy? proxy, string? group, string? password) diff --git a/NebulaAuth/Model/Exceptions/MafileNeedReloginException.cs b/NebulaAuth/Model/Exceptions/MafileNeedReloginException.cs new file mode 100644 index 0000000..dbc7004 --- /dev/null +++ b/NebulaAuth/Model/Exceptions/MafileNeedReloginException.cs @@ -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; + } +} \ No newline at end of file diff --git a/NebulaAuth/Model/NebulaSerializer.cs b/NebulaAuth/Model/NebulaSerializer.cs new file mode 100644 index 0000000..8a28f23 --- /dev/null +++ b/NebulaAuth/Model/NebulaSerializer.cs @@ -0,0 +1,90 @@ +using NebulaAuth.Model.Entities; +using Newtonsoft.Json.Linq; +using SteamLib; +using SteamLib.Utility.MafileSerialization; +using System.Collections.Generic; +using System; +using NebulaAuth.Model.Exceptions; +using Newtonsoft.Json; + +namespace NebulaAuth.Model; + +public static class NebulaSerializer +{ + public static MafileSerializer Serializer { get; } + + static NebulaSerializer() + { + Serializer = new MafileSerializer(new MafileSerializerSettings + { + DeserializationOptions = + { + AllowDeviceIdGeneration = true, + AllowSessionIdGeneration = true, + ThrowIfInvalidSteamId = false + } + }); + } + + + public static Mafile Deserialize(string cont) + { + var data = Serializer.Deserialize(cont); + var mobileData = data.Data; + var info = data.Info; + if (info.IsExtended == false) + throw new FormatException("Mafile is not extended data"); + + + var props = info.UnusedProperties ?? new Dictionary(); + var proxy = GetPropertyValue("Proxy", props); + var group = GetPropertyValue("Group", props); + var password = GetPropertyValue("Password", props); + var mafile = Mafile.FromMobileDataExtended((MobileDataExtended)mobileData, proxy, group, password); + + + if (!info.SteamIdValid) + throw new MafileNeedReloginException(mafile); + + return mafile; + } + + private static T? GetPropertyValue(string name, Dictionary dictionary) + { + if (dictionary.TryGetValue(name, out var prop) == false) return default; + var value = prop.Value; + try + { + return value.ToObject(); + } + catch (Exception ex) + { + Shell.Logger.Warn(ex, "Can't deserialize property {name}", name); + return default; + } + } + + public static string SerializeMafile(Mafile data) + { + var props = new Dictionary + { + {nameof(Mafile.Proxy), data.Proxy}, + {nameof(Mafile.Group), data.Group}, + {nameof(Mafile.Password), data.Password} + }; + return SerializeMafile(data, props); + } + + + public static string SerializeMafile(MobileDataExtended data, Dictionary? properties) + { + if (Settings.Instance.LegacyMode) + { + return MafileSerializer.SerializeLegacy(data, Formatting.Indented, properties); + } + else + { + return MafileSerializer.Serialize(data); + } + } +} \ No newline at end of file diff --git a/NebulaAuth/Model/Storage.cs b/NebulaAuth/Model/Storage.cs index feb3e1f..45e935a 100644 --- a/NebulaAuth/Model/Storage.cs +++ b/NebulaAuth/Model/Storage.cs @@ -1,19 +1,20 @@ using NebulaAuth.Model.Entities; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using SteamLib; -using SteamLib.Account; +using SteamLib.Core.Models; using SteamLib.Exceptions; using SteamLib.SteamMobile; -using SteamLib.Utility.MaFiles; using System; using System.Collections.Generic; 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; +//RETHINK public static class Storage { public const string MAFILE_F = "maFiles"; @@ -42,21 +43,20 @@ public static class Storage var hashIds = new HashSet(); var comparer = new MafileNameComparer(Settings.Instance.UseAccountNameAsMafileName); var ordered = files.Order(comparer).ToList(); - foreach (var file in ordered) + foreach (var file in ordered.Where(file => Path.GetExtension(file).EqualsIgnoreCase(".mafile"))) { - if (Path.GetExtension(file).Equals(".mafile", StringComparison.OrdinalIgnoreCase) == false) continue; try { var data = ReadMafile(file); - if (hashNames.Contains(data.AccountName) || (data.SessionData != null && hashIds.Contains(data.SessionData.SteamId))) + if (hashNames.Contains(data.AccountName) || hashIds.Contains(data.SteamId)) { DuplicateFound++; Shell.Logger.Error("Duplicate mafile {file}", Path.GetFileName(file)); continue; } hashNames.Add(data.AccountName); - if (data.SessionData != null) hashIds.Add(data.SessionData.SteamId); + if (data.SessionData != null) hashIds.Add(data.SteamId); MaFiles.Add(data); } catch (Exception ex) @@ -68,7 +68,14 @@ public static class Storage MaFiles = new ObservableCollection(MaFiles.OrderBy(m => m.AccountName)); } - + /// + /// + /// + /// + /// + /// + /// + /// public static void AddNewMafile(string path, bool overwrite) { Mafile data; @@ -77,11 +84,11 @@ public static class Storage data = ReadMafile(path); } 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"); @@ -94,14 +101,6 @@ public static class Storage throw new FormatException("Can't generate code on this mafile", ex); } - - if (data.SessionData == null) - throw new SessionInvalidException("File data is not valid. Missing SessionData") - { - Data = { { "mafile", data } } - }; - - if (overwrite == false && File.Exists(CreatePathForMafile(data))) { throw new IOException("File already exist and overwrite is False"); @@ -115,61 +114,13 @@ public static class Storage public static Mafile ReadMafile(string path) { var str = File.ReadAllText(path); - var mafile = MafileSerializer.Deserialize(str, true, out var mafileData); - if (mafileData.IsExtended == false) - throw new FormatException("Mafile is not extended data"); - - - var props = mafileData.UnusedProperties ?? new Dictionary(); - var proxy = GetPropertyValue("Proxy", props); - var group = GetPropertyValue("Group", props); - var password = GetPropertyValue("Password", props); - return Mafile.FromMobileDataExtended((MobileDataExtended)mafile, proxy, group, password); - } - - public static string SerializeMafile(Mafile data) - { - var props = new Dictionary - { - {nameof(Mafile.Proxy), data.Proxy}, - {nameof(Mafile.Group), data.Group}, - {nameof(Mafile.Password), data.Password} - }; - return SerializeMafile(data, props); - } - - public static string SerializeMafile(MobileDataExtended data, Dictionary? properties) - { - if (Settings.Instance.LegacyMode) - { - return MafileSerializer.SerializeLegacy(data, Formatting.Indented, properties); - } - else - { - return MafileSerializer.Serialize(data); - } - } - - - private static T? GetPropertyValue(string name, Dictionary dictionary) - { - if (dictionary.TryGetValue(name, out var prop) == false) return default; - var value = prop.Value; - try - { - return value.ToObject(); - } - catch (Exception ex) - { - Shell.Logger.Warn(ex, "Can't deserialize property {name}", name); - return default; - } + return NebulaSerializer.Deserialize(str); } public static void SaveMafile(Mafile data) { var path = CreatePathForMafile(data); - var str = SerializeMafile(data); + var str = NebulaSerializer.SerializeMafile(data); File.WriteAllText(Path.GetFullPath(path), str); var existed = MaFiles.SingleOrDefault(m => m.AccountName == data.AccountName); @@ -187,23 +138,14 @@ public static class Storage public static void UpdateMafile(Mafile data) { var path = CreatePathForMafile(data); - var str = SerializeMafile(data); + var str = NebulaSerializer.SerializeMafile(data); File.WriteAllText(Path.GetFullPath(path), str); } - public static void RemoveMafile(Mafile data) - { - var path = CreatePathForMafile(data); - if (File.Exists(path)) - { - File.Delete(path); - } - MaFiles.Remove(data); - } public static void MoveToRemoved(Mafile data) { var path = CreatePathForMafile(data); - var copyPath = Path.Combine(REMOVED_F, data.SessionData!.SteamId + ".mafile"); + var copyPath = Path.Combine(REMOVED_F, data.SteamId + ".mafile"); var copyPathCompleted = copyPath; var i = 0; while (File.Exists(copyPathCompleted)) @@ -218,18 +160,9 @@ public static class Storage private static string CreatePathForMafile(Mafile data) { - string fileName; - if (Settings.Instance.UseAccountNameAsMafileName) - { - fileName = CreateFileNameWithAccountName(data.AccountName); - } - else - { - if(data.SessionData == null) - throw new NullReferenceException("SessionData was null can't retrieve SteamId"); //FIXME: think about better way to handle - - fileName = CreateFileNameWithSteamId(data.SessionData.SteamId); - } + var fileName = Settings.Instance.UseAccountNameAsMafileName + ? CreateFileNameWithAccountName(data.AccountName) + : CreateFileNameWithSteamId(data.SteamId); return Path.Combine(MafileFolder, fileName); } @@ -238,13 +171,12 @@ public static class Storage private static string CreateFileNameWithSteamId(SteamId steamId) => steamId.Steam64.Id + ".mafile"; public static string? TryFindMafilePath(Mafile data) - //FIXME: write mode to mafile instead of searching it. Search sometimes represents not actual mafile (in case of duplicate steamId + accountName) { var pathFileName = Path.Combine(MafileFolder, CreateFileNameWithAccountName(data.AccountName)); string? pathSteamId = null; if (data.SessionData != null) { - pathSteamId = Path.Combine(MafileFolder, CreateFileNameWithSteamId(data.SessionData.SteamId)); + pathSteamId = Path.Combine(MafileFolder, CreateFileNameWithSteamId(data.SteamId)); } var steamIdExist = pathSteamId != null && File.Exists(pathSteamId); @@ -260,13 +192,9 @@ public static class Storage } return null; } - - public static bool ValidateCanSave(Mafile data) - { - return Settings.Instance.UseAccountNameAsMafileName || data.SessionData != null; - } } +//TODO: Refactor internal class MafileNameComparer : IComparer { public bool MafileNameMode { get; } diff --git a/NebulaAuth/NebulaAuth.csproj b/NebulaAuth/NebulaAuth.csproj index 971a2b8..e48d644 100644 --- a/NebulaAuth/NebulaAuth.csproj +++ b/NebulaAuth/NebulaAuth.csproj @@ -10,7 +10,7 @@ en;ru;ua Theme\lock.ico 7.0 - 1.5.3 + 1.5.4 true @@ -42,11 +42,6 @@ - - - - - diff --git a/NebulaAuth/PlannedChanges.txt b/NebulaAuth/PlannedChanges.txt new file mode 100644 index 0000000..bac9938 --- /dev/null +++ b/NebulaAuth/PlannedChanges.txt @@ -0,0 +1,9 @@ +• Есть люди которым нужна функция просмотра и завершения сессий аккаунта. Скорее всего в следующей версии это будет реализовано +• Сейчас, при наличии новой версии, отображается стандартное окно обновлений из библиотеки. Планируется сделать кастомный дизайн, для соответствия общему стилю. +• В приложении реализованы "совмещённые" подтверждения для торговой площадки. Т.е. при наличии более одного предмета, ожидающего подтверждение, можно либо отменить, либо подтвердить все. В планах добавить расширенный функционал, с возможностью точечного управления. +• Добавить кнопку "открыть мафайл" в меню "Файл" по аналогии с открытием папки +• Ускорить появление подсказок в интерфейсе +• Добавить запоминание пароля при привязке мафайла +• Функция переноса гуарда с мобильного устройства на ПК с созданием мафайла +• Добавить полное шифрование мафайлов по аналогии с SDA +• Сделать автоматический билд и загрузку обновления на Github при изменении в мастер ветке \ No newline at end of file diff --git a/NebulaAuth/Utility/ClipboardHelper.cs b/NebulaAuth/Utility/ClipboardHelper.cs new file mode 100644 index 0000000..084fead --- /dev/null +++ b/NebulaAuth/Utility/ClipboardHelper.cs @@ -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; + } +} \ No newline at end of file diff --git a/NebulaAuth/View/Dialogs/SetCryptPasswordDialog.xaml b/NebulaAuth/View/Dialogs/SetCryptPasswordDialog.xaml index 57ae647..051a197 100644 --- a/NebulaAuth/View/Dialogs/SetCryptPasswordDialog.xaml +++ b/NebulaAuth/View/Dialogs/SetCryptPasswordDialog.xaml @@ -19,13 +19,13 @@ - + -