Disable main window until DLLs are ready

Other code changes
This commit is contained in:
Jeddunk 2020-12-23 19:13:52 +01:00
parent 092c8f3277
commit bf7f309ea6
8 changed files with 199 additions and 121 deletions

View File

@ -5,15 +5,15 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:auto_creamapi" xmlns:local="clr-namespace:auto_creamapi"
mc:Ignorable="d" mc:Ignorable="d"
Title="DownloadWindow" Width="400" Height="200"> Title="Please wait..." Width="400" Height="200">
<Grid Margin="10,10,10,20"> <Grid Margin="10,10,10,20">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Label Content="Downloading..." HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top"/> <Label Content="Please wait..." Name="InfoLabel" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top"/>
<Label Content="..." Name="FilenameLabel" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" Grid.Row="1"/> <Label Content="" Name="FilenameLabel" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" Grid.Row="1"/>
<Label Content="00,00%" Name="PercentLabel" HorizontalAlignment="Right" Margin="0,0,0,0" VerticalAlignment="Top" Grid.Row="1"/> <Label Content="00,00%" Name="PercentLabel" HorizontalAlignment="Right" Margin="0,0,0,0" VerticalAlignment="Top" Grid.Row="1"/>
<ProgressBar Name="ProgressBar" HorizontalAlignment="Stretch" Margin="0,10,0,10" VerticalAlignment="Top" Grid.Row="2" MinHeight="20" Height="20" <ProgressBar Name="ProgressBar" HorizontalAlignment="Stretch" Margin="0,10,0,10" VerticalAlignment="Top" Grid.Row="2" MinHeight="20" Height="20"
Minimum="0" Maximum="0.99" ValueChanged="ProgressBar_OnValueChanged" Value="0"/> Minimum="0" Maximum="0.99" ValueChanged="ProgressBar_OnValueChanged" Value="0"/>

View File

@ -26,7 +26,7 @@ namespace auto_creamapi
private void ProgressBar_OnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) private void ProgressBar_OnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{ {
MyLogger.Log.Information(ProgressBar.Value.ToString("N")); //MyLogger.Log.Information(ProgressBar.Value.ToString("N"));
} }
} }
} }

View File

@ -6,7 +6,7 @@
xmlns:wcl="clr-namespace:WatermarkControlsLib.Controls;assembly=WatermarkControlsLib" xmlns:wcl="clr-namespace:WatermarkControlsLib.Controls;assembly=WatermarkControlsLib"
mc:Ignorable="d" mc:Ignorable="d"
Title="Auto-CreamAPI" Width="420" Height="540" MinWidth="420" MinHeight="540"> Title="Auto-CreamAPI" Width="420" Height="540" MinWidth="420" MinHeight="540">
<Grid> <Grid Name="MainWindowGrid">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>

View File

@ -2,6 +2,7 @@
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using auto_creamapi.Model; using auto_creamapi.Model;
@ -22,14 +23,29 @@ namespace auto_creamapi
private static CreamDllModel _dllModel; private static CreamDllModel _dllModel;
public MainWindow() public MainWindow()
{
PreInit();
InitializeComponent();
new Action(PostInit).Invoke();
}
private static void PreInit()
{ {
_cacheModel = CacheModel.Instance; _cacheModel = CacheModel.Instance;
_configModel = CreamConfigModel.Instance; _configModel = CreamConfigModel.Instance;
_dllModel = CreamDllModel.Instance; _dllModel = CreamDllModel.Instance;
InitializeComponent(); }
private async void PostInit()
{
MainWindowGrid.IsEnabled = false;
var task = _dllModel.Initialize();
await task;
_cacheModel.Languages.ForEach(x => Lang.Items.Add(x)); _cacheModel.Languages.ForEach(x => Lang.Items.Add(x));
Lang.SelectedItem = DefaultLangSelection; Lang.SelectedItem = DefaultLangSelection;
SteamDb.IsChecked = true; SteamDb.IsChecked = true;
task.Wait();
MainWindowGrid.IsEnabled = true;
Status.Text = "Ready."; Status.Text = "Ready.";
} }
@ -197,15 +213,15 @@ namespace auto_creamapi
} }
else else
{ {
Game.Text = ""; /*Game.Text = "";
AppId.Text = ""; AppId.Text = "";*/
MyLogger.Log.Error($"No app found for ID {appId}"); MyLogger.Log.Error($"No app found for ID {appId}");
} }
} }
else else
{ {
Game.Text = ""; /*Game.Text = "";
AppId.Text = ""; AppId.Text = "";*/
MyLogger.Log.Error($"SetNameById: Invalid AppID {appId}"); MyLogger.Log.Error($"SetNameById: Invalid AppID {appId}");
} }
} }
@ -213,7 +229,9 @@ namespace auto_creamapi
private void ResetFormData() private void ResetFormData()
{ {
AppId.Text = _configModel.Config.AppId.ToString(); var configAppId = _configModel.Config.AppId;
AppId.Text = configAppId.ToString();
Game.Text = configAppId > 0 ? _cacheModel.GetAppById(configAppId).Name : "";
Lang.SelectedItem = _configModel.Config.Language; Lang.SelectedItem = _configModel.Config.Language;
UnlockAll.IsChecked = _configModel.Config.UnlockAll; // public bool UnlockAll; UnlockAll.IsChecked = _configModel.Config.UnlockAll; // public bool UnlockAll;
ExtraProtection.IsChecked = _configModel.Config.ExtraProtection; // public bool ExtraProtection; ExtraProtection.IsChecked = _configModel.Config.ExtraProtection; // public bool ExtraProtection;
@ -229,7 +247,6 @@ namespace auto_creamapi
} }
ListOfDlcs.Text = dlcListString; ListOfDlcs.Text = dlcListString;
SetNameById();
} }
private void CheckExistance() private void CheckExistance()

View File

@ -68,21 +68,24 @@ namespace auto_creamapi.Model
private static void UpdateCache() private static void UpdateCache()
{ {
MyLogger.Log.Information("Updating cache...");
var updateNeeded = DateTime.Now.Subtract(File.GetCreationTimeUtc(CachePath)).TotalDays >= 1; var updateNeeded = DateTime.Now.Subtract(File.GetCreationTimeUtc(CachePath)).TotalDays >= 1;
string cacheString; string cacheString;
if (updateNeeded) if (updateNeeded)
{ {
MyLogger.Log.Information("Updating cache..."); MyLogger.Log.Information("Getting content from API...");
var client = new HttpClient(); var client = new HttpClient();
var httpCall = client.GetAsync(SteamUri); var httpCall = client.GetAsync(SteamUri);
var response = httpCall.Result; var response = httpCall.Result;
var readAsStringAsync = response.Content.ReadAsStringAsync(); var readAsStringAsync = response.Content.ReadAsStringAsync();
var responseBody = readAsStringAsync.Result; var responseBody = readAsStringAsync.Result;
MyLogger.Log.Information("Got content from API successfully. Writing to file...");
/*var writeAllTextAsync = File.WriteAllTextAsync(CachePath, responseBody, Encoding.UTF8); /*var writeAllTextAsync = File.WriteAllTextAsync(CachePath, responseBody, Encoding.UTF8);
writeAllTextAsync.RunSynchronously();*/ writeAllTextAsync.RunSynchronously();*/
File.WriteAllText(CachePath, responseBody, Encoding.UTF8); File.WriteAllText(CachePath, responseBody, Encoding.UTF8);
cacheString = responseBody; cacheString = responseBody;
MyLogger.Log.Information("Cache written to file successfully.");
} }
else else
{ {
@ -205,7 +208,7 @@ namespace auto_creamapi.Model
} }
else else
{ {
MyLogger.Log.Error($"Could not find game: {steamApp}"); MyLogger.Log.Error($"Could not get DLC: Invalid Steam App");
} }
return dlcList; return dlcList;

View File

@ -92,7 +92,7 @@ namespace auto_creamapi.Model
private void ResetConfigData() private void ResetConfigData()
{ {
Config.AppId = 0; Config.AppId = -1;
Config.Language = ""; Config.Language = "";
Config.UnlockAll = false; Config.UnlockAll = false;
Config.ExtraProtection = false; Config.ExtraProtection = false;

View File

@ -8,6 +8,7 @@ using System.Security.Cryptography;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Threading; using System.Windows.Threading;
using auto_creamapi.Services;
using auto_creamapi.Utils; using auto_creamapi.Utils;
using SharpCompress.Archives; using SharpCompress.Archives;
using SharpCompress.Common; using SharpCompress.Common;
@ -55,20 +56,19 @@ namespace auto_creamapi.Model
private bool _x64Exists; private bool _x64Exists;
private CreamDllModel() private CreamDllModel()
{
}
public async Task Initialize()
{ {
if (!(File.Exists("steam_api.dll") && File.Exists("steam_api64.dll"))) if (!(File.Exists("steam_api.dll") && File.Exists("steam_api64.dll")))
{ {
MyLogger.Log.Information("Missing files, trying to download..."); MyLogger.Log.Information("Missing files, trying to download...");
new Action(async() => await DownloadDll(Secrets.ForumUsername, Secrets.ForumPassword))(); var task = DownloadCreamApiService.DownloadAndExtract(Secrets.ForumUsername, Secrets.ForumPassword);
} await task;
else task.Wait();
{
Init();
}
} }
private void Init()
{
_creamDlls.Add(X86Arch, new CreamDll("steam_api.dll", "steam_api_o.dll")); _creamDlls.Add(X86Arch, new CreamDll("steam_api.dll", "steam_api_o.dll"));
_creamDlls.Add(X64Arch, new CreamDll("steam_api64.dll", "steam_api64_o.dll")); _creamDlls.Add(X64Arch, new CreamDll("steam_api64.dll", "steam_api64_o.dll"));
@ -83,103 +83,6 @@ namespace auto_creamapi.Model
} }
} }
private async Task DownloadDll(string username, string password)
{
var wnd = new DownloadWindow();
wnd.Show();
var container = new CookieContainer();
var handler = new HttpClientHandler {CookieContainer = container};
var client = new HttpClient(handler);
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("username", username),
new KeyValuePair<string, string>("password", password),
new KeyValuePair<string, string>("redirect", "./ucp.php?mode=login"),
new KeyValuePair<string, string>("login", "login")
});
var response1 = await client.PostAsync("https://cs.rin.ru/forum/ucp.php?mode=login", formContent);
MyLogger.Log.Debug($"Login Status Code: {response1.EnsureSuccessStatusCode().StatusCode.ToString()}");
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}");
var response2 = await client.GetAsync("https://cs.rin.ru/forum/viewtopic.php?t=70576");
MyLogger.Log.Debug(
$"Download Page Status Code: {response2.EnsureSuccessStatusCode().StatusCode.ToString()}");
var content = response2.Content.ReadAsStringAsync();
var contentResult = await content;
var expression =
new Regex(".*<a href=\"\\.(?<url>\\/download\\/file\\.php\\?id=.*)\">(?<filename>.*)<\\/a>.*");
using var reader = new StringReader(contentResult);
string line;
var archiveFileList = new Dictionary<string, string>();
while ((line = await reader.ReadLineAsync()) != null)
{
var match = expression.Match(line);
// ReSharper disable once InvertIf
if (match.Success)
{
archiveFileList.Add(match.Groups["filename"].Value,
$"https://cs.rin.ru/forum{match.Groups["url"].Value}");
MyLogger.Log.Debug(archiveFileList.LastOrDefault().Key);
}
}
/*foreach (var (filename, url) in archiveFileList)
{
MyLogger.Log.Information($"Downloading file: {filename}");
var fileResponse = await client.GetAsync(url);
var download = fileResponse.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync(filename, await download);
}*/
MyLogger.Log.Debug("Choosing first element from list...");
var (filename, url) = archiveFileList.FirstOrDefault();
MyLogger.Log.Information("Start download...");
wnd.FilenameLabel.Content = filename;
/*var fileResponse = await client.GetAsync(url);
var download = fileResponse.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync(filename, await download);
MyLogger.Log.Information($"Download success? {download.IsCompletedSuccessfully}");*/
var progress = new Progress<ICopyProgress>(
x =>
{
wnd.PercentLabel.Content = x.PercentComplete.ToString("P");
wnd.ProgressBar.Dispatcher.Invoke(() => wnd.ProgressBar.Value = x.PercentComplete,
DispatcherPriority.Background);
});
await using (var fileStream = File.OpenWrite(filename))
{
var task = client.GetAsync(url, fileStream, progress);
var response = await task;
/*if (task.IsCompletedSuccessfully)
{
wnd.PercentLabel.Content = "100,00%";
wnd.ProgressBar.Value = 1;
}*/
}
MyLogger.Log.Information("Start extraction...");
var options = new ReaderOptions {Password = "cs.rin.ru"};
var archive = ArchiveFactory.Open(filename, options);
var expression1 = new Regex(@"nonlog_build\\steam_api(?:64)?\.dll");
foreach (var entry in archive.Entries)
{
// ReSharper disable once InvertIf
if (!entry.IsDirectory && expression1.IsMatch(entry.Key))
{
MyLogger.Log.Debug(entry.Key);
entry.WriteToDirectory(Directory.GetCurrentDirectory(), new ExtractionOptions
{
ExtractFullPath = false,
Overwrite = true
});
}
}
MyLogger.Log.Information("Extraction done!");
wnd.Close();
Init();
}
public void Save() public void Save()
{ {
if (_x86Exists) CopyDll(X86Arch); if (_x86Exists) CopyDll(X86Arch);

View File

@ -0,0 +1,155 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Threading;
using auto_creamapi.Model;
using auto_creamapi.Utils;
using HttpProgress;
using SharpCompress.Archives;
using SharpCompress.Common;
using SharpCompress.Readers;
namespace auto_creamapi.Services
{
public static class DownloadCreamApiService
{
private const string ArchivePassword = "cs.rin.ru";
private static string _filename;
private static DownloadWindow _wnd;
public static async Task DownloadAndExtract(string username, string password)
{
_wnd = new DownloadWindow();
_wnd.Show();
var download = Download(username, password);
await download;
download.Wait();
var extract = Extract();
await extract;
extract.Wait();
_wnd.Close();
}
private static async Task Download(string username, string password)
{
var container = new CookieContainer();
var handler = new HttpClientHandler {CookieContainer = container};
var client = new HttpClient(handler);
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("username", username),
new KeyValuePair<string, string>("password", password),
new KeyValuePair<string, string>("redirect", "./ucp.php?mode=login"),
new KeyValuePair<string, string>("login", "login")
});
var response1 = await client.PostAsync("https://cs.rin.ru/forum/ucp.php?mode=login", formContent);
MyLogger.Log.Debug($"Login Status Code: {response1.EnsureSuccessStatusCode().StatusCode.ToString()}");
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}");
var response2 = await client.GetAsync("https://cs.rin.ru/forum/viewtopic.php?t=70576");
MyLogger.Log.Debug(
$"Download Page Status Code: {response2.EnsureSuccessStatusCode().StatusCode.ToString()}");
var content = response2.Content.ReadAsStringAsync();
var contentResult = await content;
var expression =
new Regex(".*<a href=\"\\.(?<url>\\/download\\/file\\.php\\?id=.*)\">(?<filename>.*)<\\/a>.*");
using var reader = new StringReader(contentResult);
string line;
var archiveFileList = new Dictionary<string, string>();
while ((line = await reader.ReadLineAsync()) != null)
{
var match = expression.Match(line);
// ReSharper disable once InvertIf
if (match.Success)
{
archiveFileList.Add(match.Groups["filename"].Value,
$"https://cs.rin.ru/forum{match.Groups["url"].Value}");
MyLogger.Log.Debug(archiveFileList.LastOrDefault().Key);
}
}
/*foreach (var (filename, url) in archiveFileList)
{
MyLogger.Log.Information($"Downloading file: {filename}");
var fileResponse = await client.GetAsync(url);
var download = fileResponse.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync(filename, await download);
}*/
MyLogger.Log.Debug("Choosing first element from list...");
var (filename, url) = archiveFileList.FirstOrDefault();
_filename = filename;
if (File.Exists(_filename))
{
MyLogger.Log.Information($"{_filename} already exists, skipping download...");
return;
}
MyLogger.Log.Information("Start download...");
await _wnd.FilenameLabel.Dispatcher.InvokeAsync(
() => _wnd.FilenameLabel.Content = _filename, DispatcherPriority.Background);
await _wnd.InfoLabel.Dispatcher.InvokeAsync(
() => _wnd.InfoLabel.Content = "Downloading...", DispatcherPriority.Background);
/*var fileResponse = await client.GetAsync(url);
var download = fileResponse.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync(filename, await download);
MyLogger.Log.Information($"Download success? {download.IsCompletedSuccessfully}");*/
var progress = new Progress<ICopyProgress>(
x =>
{
_wnd.PercentLabel.Dispatcher.Invoke(
() => _wnd.PercentLabel.Content = x.PercentComplete.ToString("P"),
DispatcherPriority.Background);
_wnd.ProgressBar.Dispatcher.Invoke(
() => _wnd.ProgressBar.Value = x.PercentComplete, DispatcherPriority.Background);
});
await using var fileStream = File.OpenWrite(_filename);
var task = client.GetAsync(url, fileStream, progress);
var response = await task;
if (task.IsCompletedSuccessfully)
{
_wnd.PercentLabel.Dispatcher.Invoke(
() => _wnd.PercentLabel.Content = "100,00%", DispatcherPriority.Background);
_wnd.ProgressBar.Dispatcher.Invoke(
() => _wnd.ProgressBar.Value = 1, DispatcherPriority.Background);
}
}
private static async Task Extract()
{
MyLogger.Log.Information("Start extraction...");
var options = new ReaderOptions {Password = ArchivePassword};
var archive = ArchiveFactory.Open(_filename, options);
var expression1 = new Regex(@"nonlog_build\\steam_api(?:64)?\.dll");
await _wnd.ProgressBar.Dispatcher.InvokeAsync(
() => _wnd.ProgressBar.IsIndeterminate = true, DispatcherPriority.ContextIdle);
await _wnd.FilenameLabel.Dispatcher.InvokeAsync(
() => _wnd.FilenameLabel.Content = _filename, DispatcherPriority.ContextIdle);
await _wnd.InfoLabel.Dispatcher.InvokeAsync(
() => _wnd.InfoLabel.Content = "Extracting...", DispatcherPriority.ContextIdle);
await _wnd.PercentLabel.Dispatcher.InvokeAsync(
() => _wnd.PercentLabel.Content = "100%", DispatcherPriority.ContextIdle);
foreach (var entry in archive.Entries)
{
// ReSharper disable once InvertIf
if (!entry.IsDirectory && expression1.IsMatch(entry.Key))
{
MyLogger.Log.Debug(entry.Key);
entry.WriteToDirectory(Directory.GetCurrentDirectory(), new ExtractionOptions
{
ExtractFullPath = false,
Overwrite = true
});
}
}
MyLogger.Log.Information("Extraction done!");
}
}
}