From a00e6d2d1ae1abd0642b88f9784be9a3ee6d945a Mon Sep 17 00:00:00 2001 From: Dawid Karczewski Date: Wed, 6 Oct 2021 19:55:12 +0200 Subject: [PATCH] Adds Nintendo auth & purchased games list retrieval --- .../{PSNLibrary => NintendoLibrary}/App.xaml | 0 .../NintendoLibrary/Models/NintendoModels.cs | 35 ++ .../NintendoGameController.cs} | 2 +- .../NintendoLibrary/NintendoLibrary.cs | 146 +++++++ .../NintendoLibrary.csproj} | 22 +- .../NintendoLibraryClient.cs} | 2 +- .../NintendoLibrarySettingsView.xaml} | 45 +- .../NintendoLibrarySettingsView.xaml.cs} | 6 +- .../NintendoLibrarySettingsViewModel.cs} | 23 +- .../Properties/AssemblyInfo.cs | 4 +- .../Services/NintendoAccountClient.cs | 264 +++++++++++ source/Libraries/NintendoLibrary/addon.yaml | 8 + .../Libraries/NintendoLibrary/extension.yaml | 7 + source/Libraries/NintendoLibrary/icon.png | Bin 0 -> 11960 bytes .../packages.config | 0 .../Libraries/PSNLibrary/Models/PSNModels.cs | 163 ------- source/Libraries/PSNLibrary/PSNLibrary.cs | 372 ---------------- .../PSNLibrary/Services/PSNAccountClient.cs | 413 ------------------ source/Libraries/PSNLibrary/addon.yaml | 8 - source/Libraries/PSNLibrary/extension.yaml | 7 - source/Libraries/PSNLibrary/icon.png | Bin 22254 -> 0 bytes source/Localization/en_US.xaml | 2 +- source/PlayniteExtensions.sln | 6 +- 23 files changed, 494 insertions(+), 1041 deletions(-) rename source/Libraries/{PSNLibrary => NintendoLibrary}/App.xaml (100%) create mode 100644 source/Libraries/NintendoLibrary/Models/NintendoModels.cs rename source/Libraries/{PSNLibrary/PSNGameController.cs => NintendoLibrary/NintendoGameController.cs} (84%) create mode 100644 source/Libraries/NintendoLibrary/NintendoLibrary.cs rename source/Libraries/{PSNLibrary/PSNLibrary.csproj => NintendoLibrary/NintendoLibrary.csproj} (91%) rename source/Libraries/{PSNLibrary/PSNLibraryClient.cs => NintendoLibrary/NintendoLibraryClient.cs} (80%) rename source/Libraries/{PSNLibrary/PSNLibrarySettingsView.xaml => NintendoLibrary/NintendoLibrarySettingsView.xaml} (56%) rename source/Libraries/{PSNLibrary/PSNLibrarySettingsView.xaml.cs => NintendoLibrary/NintendoLibrarySettingsView.xaml.cs} (73%) rename source/Libraries/{PSNLibrary/PSNLibrarySettingsViewModel.cs => NintendoLibrary/NintendoLibrarySettingsViewModel.cs} (60%) rename source/Libraries/{PSNLibrary => NintendoLibrary}/Properties/AssemblyInfo.cs (91%) create mode 100644 source/Libraries/NintendoLibrary/Services/NintendoAccountClient.cs create mode 100644 source/Libraries/NintendoLibrary/addon.yaml create mode 100644 source/Libraries/NintendoLibrary/extension.yaml create mode 100644 source/Libraries/NintendoLibrary/icon.png rename source/Libraries/{PSNLibrary => NintendoLibrary}/packages.config (100%) delete mode 100644 source/Libraries/PSNLibrary/Models/PSNModels.cs delete mode 100644 source/Libraries/PSNLibrary/PSNLibrary.cs delete mode 100644 source/Libraries/PSNLibrary/Services/PSNAccountClient.cs delete mode 100644 source/Libraries/PSNLibrary/addon.yaml delete mode 100644 source/Libraries/PSNLibrary/extension.yaml delete mode 100644 source/Libraries/PSNLibrary/icon.png diff --git a/source/Libraries/PSNLibrary/App.xaml b/source/Libraries/NintendoLibrary/App.xaml similarity index 100% rename from source/Libraries/PSNLibrary/App.xaml rename to source/Libraries/NintendoLibrary/App.xaml diff --git a/source/Libraries/NintendoLibrary/Models/NintendoModels.cs b/source/Libraries/NintendoLibrary/Models/NintendoModels.cs new file mode 100644 index 0000000..5f3f7b5 --- /dev/null +++ b/source/Libraries/NintendoLibrary/Models/NintendoModels.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NintendoLibrary.Models +{ + public class AuthError + { + public class Error + { + public string code { get; set; } + public string message { get; set; } + } + public Error error; + } + + public class PurchasedList + { + public int length { get; set; } + public int offset { get; set; } + public int total { get; set; } + public class Transaction + { + public string content_type { get; set; } + public string title { get; set; } + public string device_type { get; set; } + public DateTime date { get; set; } + public ulong transaction_id { get; set; } + } + + public List transactions { get; set; } + } +} diff --git a/source/Libraries/PSNLibrary/PSNGameController.cs b/source/Libraries/NintendoLibrary/NintendoGameController.cs similarity index 84% rename from source/Libraries/PSNLibrary/PSNGameController.cs rename to source/Libraries/NintendoLibrary/NintendoGameController.cs index 0efb99a..9c4407b 100644 --- a/source/Libraries/PSNLibrary/PSNGameController.cs +++ b/source/Libraries/NintendoLibrary/NintendoGameController.cs @@ -8,6 +8,6 @@ using System.Text; using System.Threading.Tasks; -namespace PSNLibrary +namespace NintendoLibrary { } diff --git a/source/Libraries/NintendoLibrary/NintendoLibrary.cs b/source/Libraries/NintendoLibrary/NintendoLibrary.cs new file mode 100644 index 0000000..31868fa --- /dev/null +++ b/source/Libraries/NintendoLibrary/NintendoLibrary.cs @@ -0,0 +1,146 @@ +using Playnite.SDK; +using Playnite.SDK.Models; +using Playnite.SDK.Plugins; +using NintendoLibrary.Models; +using NintendoLibrary.Services; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Controls; + +namespace NintendoLibrary +{ + [LoadPlugin] + public class NintendoLibrary : LibraryPluginBase + { + public NintendoLibrary(IPlayniteAPI api) : base( + "Nintendo", + Guid.Parse("e4ac81cb-1b1a-4ec9-8639-9a9633989a72"), + new LibraryPluginProperties { CanShutdownClient = false, HasCustomizedGameImport = true, HasSettings = true }, + null, + Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"icon.png"), + (_) => new NintendoLibrarySettingsView(), + api) + { + SettingsViewModel = new NintendoLibrarySettingsViewModel(this, api); + } + + private string ParsePlatform(string platformId) + { + string platform = null; + + switch (platformId) + { + case "HAC": + platform = "nintendo_switch"; + break; + + case "CTR": + platform = "nintendo_3ds"; + break; + + default: + break; + } + return platform; + } + + private string FixGameName(string name) + { + var gameName = name. + RemoveTrademarks(" "). + NormalizeGameName(). + Replace("full game", "", StringComparison.OrdinalIgnoreCase). + Trim(); + return Regex.Replace(gameName, @"\s+", " "); + } + + private List parseGames(List gamesToParse) + { + var parsedGames = new List(); + foreach (var title in gamesToParse) + { + var gameName = FixGameName(title.title); + + string platform = ParsePlatform(title.device_type); + + parsedGames.Add(new GameMetadata + { + GameId = title.transaction_id.ToString(), + Name = gameName, + Platforms = new HashSet { new MetadataSpecProperty(platform) } + }); + } + + return parsedGames; + } + + private List ParsePlayedList(NintendoAccountClient clientApi) + { + var gamesToParse = clientApi.GetPurchasedList().GetAwaiter().GetResult(); + return parseGames(gamesToParse); + } + + public override IEnumerable ImportGames(LibraryImportGamesArgs args) + { + var importedGames = new List(); + + Exception importError = null; + if (!SettingsViewModel.Settings.ConnectAccount) + { + return importedGames; + } + + try + { + var clientApi = new NintendoAccountClient(this, PlayniteApi); + var allGames = new List(); + allGames.AddRange(ParsePlayedList(clientApi)); + + // This need to happen to merge games from different APIs + foreach (var group in allGames.GroupBy(a => a.GameId)) + { + var game = group.First(); + if (PlayniteApi.ApplicationSettings.GetGameExcludedFromImport(game.GameId, Id)) + { + continue; + } + + var alreadyImported = PlayniteApi.Database.Games.FirstOrDefault(a => a.GameId == game.GameId && a.PluginId == Id); + if (alreadyImported == null) + { + game.Source = new MetadataNameProperty("Nintendo"); + importedGames.Add(PlayniteApi.Database.ImportGame(game, this)); + } + } + } + catch (Exception e) when (!Debugger.IsAttached) + { + Logger.Error(e, "Failed to import Nintendo games."); + importError = e; + } + + if (importError != null) + { + PlayniteApi.Notifications.Add(new NotificationMessage( + ImportErrorMessageId, + string.Format(PlayniteApi.Resources.GetString("LOCLibraryImportError"), Name) + + System.Environment.NewLine + importError.Message, + NotificationType.Error, + () => OpenSettingsView())); + } + else + { + PlayniteApi.Notifications.Remove(ImportErrorMessageId); + } + + return importedGames; + } + } +} \ No newline at end of file diff --git a/source/Libraries/PSNLibrary/PSNLibrary.csproj b/source/Libraries/NintendoLibrary/NintendoLibrary.csproj similarity index 91% rename from source/Libraries/PSNLibrary/PSNLibrary.csproj rename to source/Libraries/NintendoLibrary/NintendoLibrary.csproj index 81c8506..ad17b40 100644 --- a/source/Libraries/PSNLibrary/PSNLibrary.csproj +++ b/source/Libraries/NintendoLibrary/NintendoLibrary.csproj @@ -6,8 +6,8 @@ AnyCPU Library Properties - PSNLibrary - PSNLibrary + NintendoLibrary + NintendoLibrary v4.6.2 512 true @@ -151,16 +151,16 @@ Shared\PluginSettingsViewModel.cs - - - - - - - PSNLibrarySettingsView.xaml + + + + + + + NintendoLibrarySettingsView.xaml - + @@ -185,7 +185,7 @@ MSBuild:Compile Designer - + MSBuild:Compile Designer diff --git a/source/Libraries/PSNLibrary/PSNLibraryClient.cs b/source/Libraries/NintendoLibrary/NintendoLibraryClient.cs similarity index 80% rename from source/Libraries/PSNLibrary/PSNLibraryClient.cs rename to source/Libraries/NintendoLibrary/NintendoLibraryClient.cs index a1664b5..9650dec 100644 --- a/source/Libraries/PSNLibrary/PSNLibraryClient.cs +++ b/source/Libraries/NintendoLibrary/NintendoLibraryClient.cs @@ -5,6 +5,6 @@ using System.Text; using System.Threading.Tasks; -namespace PSNLibrary +namespace NintendoLibrary { } \ No newline at end of file diff --git a/source/Libraries/PSNLibrary/PSNLibrarySettingsView.xaml b/source/Libraries/NintendoLibrary/NintendoLibrarySettingsView.xaml similarity index 56% rename from source/Libraries/PSNLibrary/PSNLibrarySettingsView.xaml rename to source/Libraries/NintendoLibrary/NintendoLibrarySettingsView.xaml index 17e3338..31e3fb8 100644 --- a/source/Libraries/PSNLibrary/PSNLibrarySettingsView.xaml +++ b/source/Libraries/NintendoLibrary/NintendoLibrarySettingsView.xaml @@ -1,4 +1,4 @@ - + Text="Nintendo integration is currently broken and not supported." />--> - - - - - + IsEnabled="{Binding IsChecked, ElementName=CheckNintendoConnectAccount}">