diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..bd149f0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "SteamStorefrontAPI"] + path = SteamStorefrontAPI + url = https://git.jeddunk.xyz/jeddunk/SteamStorefrontAPI.git diff --git a/auto-creamapi.sln b/auto-creamapi.sln index c220862..78be129 100644 --- a/auto-creamapi.sln +++ b/auto-creamapi.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30413.136 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34330.188 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "auto-creamapi", "auto-creamapi\auto-creamapi.csproj", "{26060B32-199E-4366-8FDE-6B1E10E0EF62}" EndProject diff --git a/auto-creamapi/App.xaml.cs b/auto-creamapi/App.xaml.cs index 95e07c3..d78cbe5 100644 --- a/auto-creamapi/App.xaml.cs +++ b/auto-creamapi/App.xaml.cs @@ -10,7 +10,7 @@ namespace auto_creamapi { protected override void RegisterSetup() { - this.RegisterSetupType>(); + this.RegisterSetupType(); } } } \ No newline at end of file diff --git a/auto-creamapi/Converters/ListOfDLcToStringConverter.cs b/auto-creamapi/Converters/ListOfDLcToStringConverter.cs index 9904374..5691ee6 100644 --- a/auto-creamapi/Converters/ListOfDLcToStringConverter.cs +++ b/auto-creamapi/Converters/ListOfDLcToStringConverter.cs @@ -31,24 +31,26 @@ namespace auto_creamapi.Converters { MyLogger.Log.Debug("ListOfDLcToStringConverter: ConvertBack"); var stringToDlcList = StringToDlcList(value); - return stringToDlcList.GetType() == targetType ? stringToDlcList : new ObservableCollection(); + return stringToDlcList.GetType() == targetType ? stringToDlcList : []; } private static ObservableCollection StringToDlcList(string value) { var result = new ObservableCollection(); - var expression = new Regex(@"(?.*) *= *(?.*)"); + var expression = new Regex("(?.*) *= *(?.*)"); using var reader = new StringReader(value); string line; while ((line = reader.ReadLine()) != null) { var match = expression.Match(line); if (match.Success) + { result.Add(new SteamApp { AppId = int.Parse(match.Groups["id"].Value), Name = match.Groups["name"].Value }); + } } return result; diff --git a/auto-creamapi/Core/App.cs b/auto-creamapi/Core/MainApplication.cs similarity index 90% rename from auto-creamapi/Core/App.cs rename to auto-creamapi/Core/MainApplication.cs index f64d409..2201b8a 100644 --- a/auto-creamapi/Core/App.cs +++ b/auto-creamapi/Core/MainApplication.cs @@ -4,7 +4,7 @@ using MvvmCross.ViewModels; namespace auto_creamapi.Core { - public class App : MvxApplication + public class MainApplication : MvxApplication { public override void Initialize() { diff --git a/auto-creamapi/Services/CacheService.cs b/auto-creamapi/Services/CacheService.cs index e7637db..223bbe5 100644 --- a/auto-creamapi/Services/CacheService.cs +++ b/auto-creamapi/Services/CacheService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Net.Http; @@ -32,11 +33,7 @@ namespace auto_creamapi.Services private const string CachePath = "steamapps.json"; private const string SteamUri = "https://api.steampowered.com/ISteamApps/GetAppList/v2/"; - private const string UserAgent = - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " + - "Chrome/87.0.4280.88 Safari/537.36"; - - private HashSet _cache = new HashSet(); + private HashSet _cache = []; public async Task Initialize() { @@ -84,122 +81,149 @@ namespace auto_creamapi.Services public SteamApp GetAppByName(string name) { - MyLogger.Log.Information($"Trying to get app {name}"); + MyLogger.Log.Information("Trying to get app {Name}", name); var comparableName = Regex.Replace(name, Misc.SpecialCharsRegex, "").ToLower(); var app = _cache.FirstOrDefault(x => x.CompareName(comparableName)); - if (app != null) MyLogger.Log.Information($"Successfully got app {app}"); + if (app != null) MyLogger.Log.Information("Successfully got app {App}", app); return app; } public SteamApp GetAppById(int appid) { - MyLogger.Log.Information($"Trying to get app with ID {appid}"); + MyLogger.Log.Information("Trying to get app with ID {AppId}", appid); var app = _cache.FirstOrDefault(x => x.AppId.Equals(appid)); - if (app != null) MyLogger.Log.Information($"Successfully got app {app}"); + if (app != null) MyLogger.Log.Information("Successfully got app {App}", app); return app; } public async Task> GetListOfDlc(SteamApp steamApp, bool useSteamDb, bool ignoreUnknown) { - MyLogger.Log.Information("Get DLC"); + MyLogger.Log.Debug("Start: GetListOfDlc"); var dlcList = new List(); - if (steamApp != null) + try { - var steamAppDetails = await AppDetails.GetAsync(steamApp.AppId).ConfigureAwait(false); - if (steamAppDetails != null) + if (steamApp != null) { - MyLogger.Log.Debug($"Type for Steam App {steamApp.Name}: \"{steamAppDetails.Type}\""); - if (steamAppDetails.Type == "game" | steamAppDetails.Type == "demo") + var steamAppDetails = await AppDetails.GetAsync(steamApp.AppId).ConfigureAwait(false); + if (steamAppDetails != null) { - steamAppDetails.DLC.ForEach(x => + MyLogger.Log.Debug("Type for Steam App {Name}: \"{Type}\"", steamApp.Name, + steamAppDetails.Type); + if (steamAppDetails.Type == "game" || steamAppDetails.Type == "demo") { - var result = _cache.FirstOrDefault(y => y.AppId.Equals(x)); - if (result == null) return; - var dlcDetails = AppDetails.GetAsync(x).Result; - dlcList.Add(dlcDetails != null - ? new SteamApp { AppId = dlcDetails.SteamAppId, Name = dlcDetails.Name } - : new SteamApp { AppId = x, Name = $"Unknown DLC {x}" }); - }); - - dlcList.ForEach(x => MyLogger.Log.Debug($"{x.AppId}={x.Name}")); - MyLogger.Log.Information("Got DLC successfully..."); - - if (!useSteamDb) return dlcList; - - // Get DLC from SteamDB - // Get Cloudflare cookie - // Scrape and parse HTML page - // Add missing to DLC list - var steamDbUri = new Uri($"https://steamdb.info/app/{steamApp.AppId}/dlc/"); - - var client = new HttpClient(); - client.DefaultRequestHeaders.UserAgent.ParseAdd(UserAgent); - - MyLogger.Log.Information("Get SteamDB App"); - var httpCall = client.GetAsync(steamDbUri); - var response = await httpCall.ConfigureAwait(false); - MyLogger.Log.Debug(httpCall.Status.ToString()); - MyLogger.Log.Debug(response.EnsureSuccessStatusCode().ToString()); - - var readAsStringAsync = response.Content.ReadAsStringAsync(); - var responseBody = await readAsStringAsync.ConfigureAwait(false); - MyLogger.Log.Debug(readAsStringAsync.Status.ToString()); - - var parser = new HtmlParser(); - var doc = parser.ParseDocument(responseBody); - // Console.WriteLine(doc.DocumentElement.OuterHtml); - - var query1 = doc.QuerySelector("#dlc"); - if (query1 != null) - { - var query2 = query1.QuerySelectorAll(".app"); - foreach (var element in query2) + steamAppDetails.DLC.ForEach(x => { - var dlcId = element.GetAttribute("data-appid"); - var query3 = element.QuerySelectorAll("td"); - var dlcName = query3 == null - ? $"Unknown DLC {dlcId}" - : query3[1].Text().Replace("\n", "").Trim(); + var result = _cache.FirstOrDefault(y => y.AppId.Equals(x)); + if (result == null) return; + var dlcDetails = AppDetails.GetAsync(x).Result; + dlcList.Add(dlcDetails != null + ? new SteamApp { AppId = dlcDetails.SteamAppId, Name = dlcDetails.Name } + : new SteamApp { AppId = x, Name = $"Unknown DLC {x}" }); + }); - if (ignoreUnknown && dlcName.Contains("SteamDB Unknown App")) + dlcList.ForEach(x => MyLogger.Log.Debug("{AppId}={Name}", x.AppId, x.Name)); + MyLogger.Log.Information("Got DLC successfully..."); + + // Return if Steam DB is deactivated + if (!useSteamDb) return dlcList; + + string steamDbUrl = $"https://steamdb.info/app/{steamApp.AppId}/dlc/"; + + var client = new HttpClient(); + string archiveJson = await client.GetStringAsync($"https://archive.org/wayback/available?url={steamDbUrl}"); + var archiveResult = JsonSerializer.Deserialize(archiveJson); + + if (archiveResult == null || archiveResult.ArchivedSnapshots.Closest?.Status != "200") + { + return dlcList; + } + + //language=regex + const string pattern = @"^(https?:\/\/web\.archive\.org\/web\/\d+)(\/.+)$"; + const string substitution = "$1id_$2"; + const RegexOptions options = RegexOptions.Multiline; + + Regex regex = new(pattern, options); + string newUrl = regex.Replace(archiveResult.ArchivedSnapshots.Closest.Url, substitution); + + //client.DefaultRequestHeaders.UserAgent.ParseAdd(UserAgent); + + MyLogger.Log.Information("Get SteamDB App"); + var httpCall = client.GetAsync(newUrl); + var response = await httpCall.ConfigureAwait(false); + MyLogger.Log.Debug("{Status}", httpCall.Status.ToString()); + MyLogger.Log.Debug("{Boolean}", response.IsSuccessStatusCode.ToString()); + + response.EnsureSuccessStatusCode(); + + var readAsStringAsync = response.Content.ReadAsStringAsync(); + var responseBody = await readAsStringAsync.ConfigureAwait(false); + MyLogger.Log.Debug("{Status}", readAsStringAsync.Status.ToString()); + + var parser = new HtmlParser(); + var doc = parser.ParseDocument(responseBody); + // Console.WriteLine(doc.DocumentElement.OuterHtml); + + var query1 = doc.QuerySelector("#dlc"); + if (query1 != null) + { + var query2 = query1.QuerySelectorAll(".app"); + foreach (var element in query2) { - MyLogger.Log.Information($"Skipping SteamDB Unknown App {dlcId}"); - } - else - { - var dlcApp = new SteamApp {AppId = Convert.ToInt32(dlcId), Name = dlcName}; - var i = dlcList.FindIndex(x => x.AppId.Equals(dlcApp.AppId)); - if (i > -1) + var dlcId = element.GetAttribute("data-appid"); + var query3 = element.QuerySelectorAll("td"); + var dlcName = query3 == null + ? $"Unknown DLC {dlcId}" + : query3[1].Text().Replace("\n", "").Trim(); + + if (ignoreUnknown && dlcName.Contains("SteamDB Unknown App")) { - if (dlcList[i].Name.Contains("Unknown DLC")) dlcList[i] = dlcApp; + MyLogger.Log.Information("Skipping SteamDB Unknown App {DlcId}", dlcId); } else { - dlcList.Add(dlcApp); + var dlcApp = new SteamApp { AppId = Convert.ToInt32(dlcId), Name = dlcName }; + var i = dlcList.FindIndex(x => x.AppId.Equals(dlcApp.AppId)); + if (i > -1) + { + if (dlcList[i].Name.Contains("Unknown DLC")) dlcList[i] = dlcApp; + } + else + { + dlcList.Add(dlcApp); + } } } + + dlcList.ForEach(x => MyLogger.Log.Debug("{AppId}={Name}", x.AppId, x.Name)); + MyLogger.Log.Information("Got DLC from SteamDB successfully..."); + } + else + { + MyLogger.Log.Error("Could not get DLC from SteamDB!"); } - dlcList.ForEach(x => MyLogger.Log.Debug($"{x.AppId}={x.Name}")); - MyLogger.Log.Information("Got DLC from SteamDB successfully..."); } else { - MyLogger.Log.Error("Could not get DLC from SteamDB!"); + MyLogger.Log.Error("Could not get DLC: Steam App is not of type: \"Game\""); } } else { - MyLogger.Log.Error("Could not get DLC: Steam App is not of type: \"Game\""); + MyLogger.Log.Error("Could not get DLC: Could not get Steam App details"); } } else { - MyLogger.Log.Error("Could not get DLC..."); + MyLogger.Log.Error("Could not get DLC: Invalid Steam App"); } + + //return dlcList; } - else + catch (Exception e) { - MyLogger.Log.Error("Could not get DLC: Invalid Steam App"); + MyLogger.Log.Error("Could not get DLC!"); + MyLogger.Log.Debug(e.Demystify(), "Exception thrown!"); } return dlcList; diff --git a/auto-creamapi/Services/CreamConfigService.cs b/auto-creamapi/Services/CreamConfigService.cs index acd2a3e..d21f13d 100644 --- a/auto-creamapi/Services/CreamConfigService.cs +++ b/auto-creamapi/Services/CreamConfigService.cs @@ -65,7 +65,7 @@ namespace auto_creamapi.Services _configFilePath = configFilePath; if (File.Exists(configFilePath)) { - MyLogger.Log.Information($"Config file found @ {configFilePath}, parsing..."); + MyLogger.Log.Information("Config file found @ {ConfigFilePath}, parsing...", configFilePath); var parser = new FileIniDataParser(); var data = parser.ReadFile(_configFilePath, Encoding.UTF8); @@ -83,7 +83,7 @@ namespace auto_creamapi.Services } else { - MyLogger.Log.Information($"Config file does not exist @ {configFilePath}, skipping..."); + MyLogger.Log.Information("Config file does not exist @ {ConfigFilePath}, skipping...", configFilePath); ResetConfigData(); } } diff --git a/auto-creamapi/Services/CreamDllService.cs b/auto-creamapi/Services/CreamDllService.cs index 9cee2df..de3c9b7 100644 --- a/auto-creamapi/Services/CreamDllService.cs +++ b/auto-creamapi/Services/CreamDllService.cs @@ -66,8 +66,8 @@ namespace auto_creamapi.Services var x64File = Path.Combine(TargetPath, "steam_api64.dll"); _x86Exists = File.Exists(x86File); _x64Exists = File.Exists(x64File); - if (_x86Exists) MyLogger.Log.Information($"x86 SteamAPI DLL found: {x86File}"); - if (_x64Exists) MyLogger.Log.Information($"x64 SteamAPI DLL found: {x64File}"); + if (_x86Exists) MyLogger.Log.Information("x86 SteamAPI DLL found: {X}", x86File); + if (_x64Exists) MyLogger.Log.Information("x64 SteamAPI DLL found: {X}", x64File); } public bool CreamApiApplied() @@ -83,7 +83,7 @@ namespace auto_creamapi.Services var targetSteamApiDll = Path.Combine(TargetPath, _creamDlls[arch].Filename); var targetSteamApiOrigDll = Path.Combine(TargetPath, _creamDlls[arch].OrigFilename); var targetSteamApiDllBackup = Path.Combine(TargetPath, $"{_creamDlls[arch].Filename}.backup"); - MyLogger.Log.Information($"Setting up CreamAPI DLL @ {TargetPath} (arch :{arch})"); + MyLogger.Log.Information("Setting up CreamAPI DLL @ {TargetPath} (arch :{Arch})", TargetPath, arch); // Create backup of steam_api.dll File.Copy(targetSteamApiDll, targetSteamApiDllBackup, true); // Check if steam_api_o.dll already exists diff --git a/auto-creamapi/Services/DownloadCreamApiService.cs b/auto-creamapi/Services/DownloadCreamApiService.cs index 870c755..ba9f75c 100644 --- a/auto-creamapi/Services/DownloadCreamApiService.cs +++ b/auto-creamapi/Services/DownloadCreamApiService.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Http; -using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using auto_creamapi.Messenger; @@ -37,6 +36,8 @@ namespace auto_creamapi.Services var container = new CookieContainer(); var handler = new HttpClientHandler {CookieContainer = container}; var client = new HttpClient(handler); + client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) " + + "Gecko/20100101 Firefox/86.0"); var formContent = new FormUrlEncodedContent(new[] { new KeyValuePair("username", username), @@ -47,14 +48,15 @@ namespace auto_creamapi.Services MyLogger.Log.Debug("Download: post login"); var response1 = await client.PostAsync("https://cs.rin.ru/forum/ucp.php?mode=login", formContent) .ConfigureAwait(false); - MyLogger.Log.Debug($"Login Status Code: {response1.EnsureSuccessStatusCode().StatusCode.ToString()}"); + MyLogger.Log.Debug("Login Status Code: {StatusCode}", + response1.EnsureSuccessStatusCode().StatusCode); var cookie = container.GetCookies(new Uri("https://cs.rin.ru/forum/ucp.php?mode=login")) .FirstOrDefault(c => c.Name.Contains("_sid")); - MyLogger.Log.Debug($"Login Cookie: {cookie}"); + MyLogger.Log.Debug("Login Cookie: {Cookie}", cookie); var response2 = await client.GetAsync("https://cs.rin.ru/forum/viewtopic.php?t=70576") .ConfigureAwait(false); - MyLogger.Log.Debug( - $"Download Page Status Code: {response2.EnsureSuccessStatusCode().StatusCode.ToString()}"); + MyLogger.Log.Debug("Download Page Status Code: {StatusCode}", + response2.EnsureSuccessStatusCode().StatusCode); var content = response2.Content.ReadAsStringAsync(); var contentResult = await content.ConfigureAwait(false); @@ -71,7 +73,7 @@ namespace auto_creamapi.Services { archiveFileList.Add(match.Groups["filename"].Value, $"https://cs.rin.ru/forum{match.Groups["url"].Value}"); - MyLogger.Log.Debug(archiveFileList.LastOrDefault().Key); + MyLogger.Log.Debug("{X}", archiveFileList.LastOrDefault().Key); } } @@ -79,7 +81,7 @@ namespace auto_creamapi.Services var (filename, url) = archiveFileList.FirstOrDefault(); if (File.Exists(filename)) { - MyLogger.Log.Information($"{filename} already exists, skipping download..."); + MyLogger.Log.Information("{Filename} already exists, skipping download...", filename); return filename; } @@ -102,7 +104,7 @@ namespace auto_creamapi.Services const string nonlogBuild = "nonlog_build"; const string steamApi64Dll = "steam_api64.dll"; const string steamApiDll = "steam_api.dll"; - MyLogger.Log.Information($@"Start extraction of ""{filename}""..."); + MyLogger.Log.Information(@"Start extraction of ""{Filename}""...", filename); var nonlogBuildPath = Path.Combine(cwd, nonlogBuild); if (Directory.Exists(nonlogBuildPath)) Directory.Delete(nonlogBuildPath, true); diff --git a/auto-creamapi/Setup.cs b/auto-creamapi/Setup.cs new file mode 100644 index 0000000..9a5682a --- /dev/null +++ b/auto-creamapi/Setup.cs @@ -0,0 +1,29 @@ +using auto_creamapi.Core; +using auto_creamapi.Utils; +using Microsoft.Extensions.Logging; +using MvvmCross.Platforms.Wpf.Core; +using Serilog; +using Serilog.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace auto_creamapi +{ + public class Setup : MvxWpfSetup + { + protected override ILoggerFactory CreateLogFactory() + { + Log.Logger = MyLogger.Log; + + return new SerilogLoggerFactory(); + } + + protected override ILoggerProvider CreateLogProvider() + { + return new SerilogLoggerProvider(); + } + } +} diff --git a/auto-creamapi/Utils/AvailabeArchive.cs b/auto-creamapi/Utils/AvailabeArchive.cs new file mode 100644 index 0000000..f7561b1 --- /dev/null +++ b/auto-creamapi/Utils/AvailabeArchive.cs @@ -0,0 +1,35 @@ +using System.Text.Json.Serialization; + +namespace auto_creamapi.Utils +{ + + public class AvailableArchive + { + [JsonPropertyName("url")] + public string Url { get; set; } + + [JsonPropertyName("archived_snapshots")] + public ArchivedSnapshot ArchivedSnapshots { get; set; } + } + + public class ArchivedSnapshot + { + [JsonPropertyName("closest")] + public Closest Closest { get; set; } + } + + public class Closest + { + [JsonPropertyName("status")] + public string Status { get; set; } + + [JsonPropertyName("available")] + public bool Available { get; set; } + + [JsonPropertyName("url")] + public string Url { get; set; } + + [JsonPropertyName("timestamp")] + public string Timestamp { get; set; } + } +} diff --git a/auto-creamapi/Utils/ISecrets.cs b/auto-creamapi/Utils/ISecrets.cs new file mode 100644 index 0000000..01840ac --- /dev/null +++ b/auto-creamapi/Utils/ISecrets.cs @@ -0,0 +1,8 @@ +namespace auto_creamapi.Utils +{ + public interface ISecrets + { + public string ForumUsername(); + public string ForumPassword(); + } +} \ No newline at end of file diff --git a/auto-creamapi/Utils/Misc.cs b/auto-creamapi/Utils/Misc.cs index 3290f47..5e0883c 100644 --- a/auto-creamapi/Utils/Misc.cs +++ b/auto-creamapi/Utils/Misc.cs @@ -3,11 +3,11 @@ using System.Collections.ObjectModel; namespace auto_creamapi.Utils { - public class Misc + public static class Misc { public const string SpecialCharsRegex = "[^0-9a-zA-Z]+"; public const string DefaultLanguageSelection = "english"; - public static readonly ObservableCollection DefaultLanguages = new ObservableCollection(new[] + public static readonly ObservableCollection DefaultLanguages = new(new[] { "arabic", "bulgarian", diff --git a/auto-creamapi/Utils/MyLogger.cs b/auto-creamapi/Utils/MyLogger.cs index 9e1b19a..903e5a9 100644 --- a/auto-creamapi/Utils/MyLogger.cs +++ b/auto-creamapi/Utils/MyLogger.cs @@ -1,12 +1,14 @@ using Serilog; using Serilog.Core; +using Serilog.Exceptions; namespace auto_creamapi.Utils { - public class MyLogger + public static class MyLogger { public static readonly Logger Log = new LoggerConfiguration() .MinimumLevel.Debug() + .Enrich.WithExceptionDetails() .WriteTo.Console() .WriteTo.File("autocreamapi.log", rollingInterval: RollingInterval.Day) .CreateLogger(); diff --git a/auto-creamapi/Utils/Secrets.EXAMPLE.cs b/auto-creamapi/Utils/Secrets.EXAMPLE.cs deleted file mode 100644 index f885562..0000000 --- a/auto-creamapi/Utils/Secrets.EXAMPLE.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace auto_creamapi.Utils -{ - /// - /// To use this: - /// Rename file Secrets.EXAMPLE.cs to Secrets.cs - /// Rename class Secrets_REMOVETHIS to Secrets - /// Enter the relevant info below - /// - public class Secrets_REMOVETHIS - { - public const string Username = "Enter username here"; - public const string Password = "Enter password here"; - } -} \ No newline at end of file diff --git a/auto-creamapi/ViewModels/DownloadViewModel.cs b/auto-creamapi/ViewModels/DownloadViewModel.cs index c580d8d..238509c 100644 --- a/auto-creamapi/ViewModels/DownloadViewModel.cs +++ b/auto-creamapi/ViewModels/DownloadViewModel.cs @@ -1,32 +1,37 @@ +using System; using System.Threading.Tasks; +using System.Windows; using auto_creamapi.Messenger; using auto_creamapi.Services; using auto_creamapi.Utils; -using MvvmCross.Logging; +using Microsoft.Extensions.Logging; using MvvmCross.Navigation; using MvvmCross.Plugin.Messenger; using MvvmCross.ViewModels; namespace auto_creamapi.ViewModels { - public class DownloadViewModel : MvxNavigationViewModel { private readonly IDownloadCreamApiService _download; private readonly IMvxNavigationService _navigationService; private readonly MvxSubscriptionToken _token; + private readonly ILogger _logger; private string _filename; private string _info; private double _progress; - public DownloadViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService, - IDownloadCreamApiService download, IMvxMessenger messenger) : base(logProvider, navigationService) + private readonly Secrets _secrets = new(); + + public DownloadViewModel(ILoggerFactory loggerFactory, IMvxNavigationService navigationService, + IDownloadCreamApiService download, IMvxMessenger messenger) : base(loggerFactory, navigationService) { _navigationService = navigationService; + _logger = loggerFactory.CreateLogger(); _download = download; _token = messenger.Subscribe(OnProgressMessage); - MyLogger.Log.Debug(messenger.CountSubscriptionsFor().ToString()); + _logger.LogDebug("{Count}", messenger.CountSubscriptionsFor()); } public string InfoLabel @@ -62,25 +67,38 @@ namespace auto_creamapi.ViewModels public string ProgressPercent => _progress.ToString("P2"); - public override async Task Initialize() + public override void Prepare() { - await base.Initialize().ConfigureAwait(false); InfoLabel = "Please wait..."; FilenameLabel = ""; Progress = 0.0; - var download = _download.Download(Secrets.ForumUsername, Secrets.ForumPassword); - var filename = await download.ConfigureAwait(false); - /*var extract = _download.Extract(filename); - await extract;*/ - var extract = _download.Extract(filename); - await extract.ConfigureAwait(false); - _token.Dispose(); - await _navigationService.Close(this).ConfigureAwait(false); + } + + public override async Task Initialize() + { + try + { + await base.Initialize().ConfigureAwait(false); + var download = _download.Download(_secrets.ForumUsername(), _secrets.ForumPassword()); + var filename = await download.ConfigureAwait(false); + var extract = _download.Extract(filename); + await extract.ConfigureAwait(false); + _token.Dispose(); + await _navigationService.Close(this).ConfigureAwait(false); + } + catch (Exception e) + { + MessageBox.Show("Could not download CreamAPI!\nPlease add CreamAPI DLLs manually!\nShutting down...", + "Error", MessageBoxButton.OK, MessageBoxImage.Error); + _token.Dispose(); + await _navigationService.Close(this).ConfigureAwait(false); + Console.WriteLine(e); + throw; + } } private void OnProgressMessage(ProgressMessage obj) { - //MyLogger.Log.Debug($"{obj.Filename}: {obj.BytesTransferred}"); InfoLabel = obj.Info; FilenameLabel = obj.Filename; Progress = obj.PercentComplete; diff --git a/auto-creamapi/ViewModels/MainViewModel.cs b/auto-creamapi/ViewModels/MainViewModel.cs index eed6b30..296164d 100644 --- a/auto-creamapi/ViewModels/MainViewModel.cs +++ b/auto-creamapi/ViewModels/MainViewModel.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using auto_creamapi.Models; using auto_creamapi.Services; using auto_creamapi.Utils; +using Microsoft.Extensions.Logging; using Microsoft.Win32; using MvvmCross.Commands; using MvvmCross.Navigation; @@ -19,6 +20,7 @@ namespace auto_creamapi.ViewModels private readonly ICacheService _cache; private readonly ICreamConfigService _config; + private readonly ILogger _logger; private readonly ICreamDllService _dll; private readonly IMvxNavigationService _navigationService; private int _appId; @@ -43,9 +45,10 @@ namespace auto_creamapi.ViewModels //private const string DlcRegexPattern = @"(?.*) *= *(?.*)"; public MainViewModel(ICacheService cache, ICreamConfigService config, ICreamDllService dll, - IMvxNavigationService navigationService) + IMvxNavigationService navigationService, ILoggerFactory loggerFactory) { _navigationService = navigationService; + _logger = loggerFactory.CreateLogger(); _cache = cache; _config = config; _dll = dll; @@ -56,7 +59,7 @@ namespace auto_creamapi.ViewModels { base.Prepare(); _config.Initialize(); - var tasks = new List {_cache.Initialize()}; + var tasks = new List { _cache.Initialize() }; if (!File.Exists("steam_api.dll") | !File.Exists("steam_api64.dll")) tasks.Add(_navigationService.Navigate()); //tasks.Add(_navigationService.Navigate()); @@ -69,11 +72,6 @@ namespace auto_creamapi.ViewModels Status = "Ready."; } - public override Task Initialize() - { - return base.Initialize(); - } - // // COMMANDS // // public IMvxCommand OpenFileCommand => new MvxAsyncCommand(OpenFile); @@ -88,6 +86,8 @@ namespace auto_creamapi.ViewModels public IMvxCommand GoToForumThreadCommand => new MvxCommand(GoToForumThread); + public IMvxCommand GoToSteamdbCommand => new MvxCommand(GoToSteamdb); + // // ATTRIBUTES // // public bool MainWindowEnabled @@ -275,7 +275,7 @@ namespace auto_creamapi.ViewModels var s = index > -1 ? strings[index] : null; if (s != null) GameName = s; await Search().ConfigureAwait(false); - await GetListOfDlc().ConfigureAwait(false); + // await GetListOfDlc().ConfigureAwait(false); } Status = "Ready."; @@ -311,11 +311,11 @@ namespace auto_creamapi.ViewModels } } - await GetListOfDlc().ConfigureAwait(false); + // await GetListOfDlc().ConfigureAwait(false); } else { - MyLogger.Log.Warning("Empty game name, cannot initiate search!"); + _logger.LogWarning("Empty game name, cannot initiate search!"); } MainWindowEnabled = true; @@ -323,10 +323,10 @@ namespace auto_creamapi.ViewModels private async Task GetListOfDlc() { - Status = "Trying to get DLC..."; + Status = "Trying to get DLC, please wait..."; if (AppId > 0) { - var app = new SteamApp {AppId = AppId, Name = GameName}; + var app = new SteamApp { AppId = AppId, Name = GameName }; var task = _cache.GetListOfDlc(app, UseSteamDb, IgnoreUnknown); MainWindowEnabled = false; var listOfDlc = await task.ConfigureAwait(false); @@ -346,7 +346,7 @@ namespace auto_creamapi.ViewModels else { Status = $"Could not get DLC for AppID {AppId}"; - MyLogger.Log.Error($"GetListOfDlc: Invalid AppID {AppId}"); + _logger.LogError("GetListOfDlc: Invalid AppID {AppId}", AppId); } } @@ -385,9 +385,7 @@ namespace auto_creamapi.ViewModels { var searchTerm = AppId; //$"{GameName.Replace(" ", "+")}+{appId}"; var destinationUrl = - "https://cs.rin.ru/forum/search.php?keywords=" + - searchTerm + - "&terms=any&fid[]=10&sf=firstpost&sr=topics&submit=Search"; + $"https://cs.rin.ru/forum/search.php?keywords={searchTerm}&terms=any&fid[]=10&sf=firstpost&sr=topics&submit=Search"; var uri = new Uri(destinationUrl); var process = new ProcessStartInfo(uri.AbsoluteUri) { @@ -397,7 +395,29 @@ namespace auto_creamapi.ViewModels } else { - MyLogger.Log.Error($"OpenURL: Invalid AppID {AppId}"); + _logger.LogError("OpenURL: Invalid AppID {AppId}", AppId); + Status = $"Could not open URL: Invalid AppID {AppId}"; + } + } + + private void GoToSteamdb() + { + Status = "Opening URL..."; + if (AppId > 0) + { + var searchTerm = AppId; //$"{GameName.Replace(" ", "+")}+{appId}"; + var destinationUrl = + $"https://steamdb.info/app/{searchTerm}/dlc/"; + var uri = new Uri(destinationUrl); + var process = new ProcessStartInfo(uri.AbsoluteUri) + { + UseShellExecute = true + }; + Process.Start(process); + } + else + { + _logger.LogError("OpenURL: Invalid AppID {AppId}", AppId); Status = $"Could not open URL: Invalid AppID {AppId}"; } } diff --git a/auto-creamapi/ViewModels/SearchResultViewModel.cs b/auto-creamapi/ViewModels/SearchResultViewModel.cs index 17804ca..82e401c 100644 --- a/auto-creamapi/ViewModels/SearchResultViewModel.cs +++ b/auto-creamapi/ViewModels/SearchResultViewModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using auto_creamapi.Models; using auto_creamapi.Utils; +using Microsoft.Extensions.Logging; using MvvmCross.Commands; using MvvmCross.Logging; using MvvmCross.Navigation; @@ -13,16 +14,18 @@ namespace auto_creamapi.ViewModels IMvxViewModel, SteamApp> { private readonly IMvxNavigationService _navigationService; + private readonly ILogger _logger; private IEnumerable _steamApps; /*public override async Task Initialize() { await base.Initialize(); }*/ - public SearchResultViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService) : base( - logProvider, navigationService) + public SearchResultViewModel(ILoggerFactory loggerFactory, IMvxNavigationService navigationService) : base( + loggerFactory, navigationService) { _navigationService = navigationService; + _logger = loggerFactory.CreateLogger(); } public IEnumerable Apps @@ -55,9 +58,11 @@ namespace auto_creamapi.ViewModels public override void ViewDestroy(bool viewFinishing = true) { - if (viewFinishing && CloseCompletionSource != null && !CloseCompletionSource.Task.IsCompleted && + if (viewFinishing && CloseCompletionSource?.Task.IsCompleted == false && !CloseCompletionSource.Task.IsFaulted) + { CloseCompletionSource?.TrySetCanceled(); + } base.ViewDestroy(viewFinishing); } @@ -66,7 +71,7 @@ namespace auto_creamapi.ViewModels { if (Selected != null) { - MyLogger.Log.Information($"Successfully got app {Selected}"); + _logger.LogInformation("Successfully got app {Selected}", Selected); await _navigationService.Close(this, Selected).ConfigureAwait(false); } } diff --git a/auto-creamapi/Views/MainView.xaml b/auto-creamapi/Views/MainView.xaml index 154e9f4..719893e 100644 --- a/auto-creamapi/Views/MainView.xaml +++ b/auto-creamapi/Views/MainView.xaml @@ -56,9 +56,18 @@ - - Search for cs.rin.ru thread - + + + + + + + Search for cs.rin.ru thread... + + + Open SteamDB DLC page... + + - - WinExe - netcoreapp3.1 - auto_creamapi - true - 2.1.6 - auto-creamapi - Jeddunk - jeddunk.xyz - 2.1.6 - 2.1.6 - + + WinExe + net8.0-windows + auto_creamapi + true + 2.2.0 + auto-creamapi + Jeddunk + jeddunk.xyz + 2.2.0 + 2.2.0 + - - none - + + none + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + \ No newline at end of file