SearchResultView and DownloadView implemented;

Ignore whitespaces and special chars when looking for games;
This commit is contained in:
Jeddunk 2020-12-28 15:27:37 +01:00
parent aada82693d
commit 73baa27245
26 changed files with 783 additions and 642 deletions

View File

@ -1,6 +1,5 @@
using MvvmCross.Core;
using MvvmCross.Platforms.Wpf.Core;
using MvvmCross.Platforms.Wpf.Views;
namespace auto_creamapi
{

View File

@ -1,30 +1,40 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using auto_creamapi.Models;
using auto_creamapi.Utils;
using MvvmCross.Converters;
using MvvmCross.Platforms.Wpf.Converters;
namespace auto_creamapi.Converters
{
public class ListOfDLcToStringConverter : MvxValueConverter<List<SteamApp>, string>
public class ListOfDLcToStringNativeConverter : MvxNativeValueConverter<ListOfDLcToStringConverter>
{
protected override string Convert(List<SteamApp> value, Type targetType, object parameter, CultureInfo culture)
}
public class ListOfDLcToStringConverter : MvxValueConverter<ObservableCollection<SteamApp>, string>
{
protected override string Convert(ObservableCollection<SteamApp> value, Type targetType, object parameter,
CultureInfo culture)
{
MyLogger.Log.Debug("ListOfDLcToStringConverter: Convert");
var dlcListToString = DlcListToString(value);
return dlcListToString.GetType() == targetType ? dlcListToString : "";
}
protected override List<SteamApp> ConvertBack(string value, Type targetType, object parameter, CultureInfo culture)
protected override ObservableCollection<SteamApp> ConvertBack(string value, Type targetType, object parameter,
CultureInfo culture)
{
MyLogger.Log.Debug("ListOfDLcToStringConverter: ConvertBack");
var stringToDlcList = StringToDlcList(value);
return stringToDlcList.GetType() == targetType ? stringToDlcList : new List<SteamApp>();
return stringToDlcList.GetType() == targetType ? stringToDlcList : new ObservableCollection<SteamApp>();
}
private static List<SteamApp> StringToDlcList(string value)
private static ObservableCollection<SteamApp> StringToDlcList(string value)
{
var result = new List<SteamApp>();
var result = new ObservableCollection<SteamApp>();
var expression = new Regex(@"(?<id>.*) *= *(?<name>.*)");
using var reader = new StringReader(value);
string line;
@ -32,22 +42,21 @@ namespace auto_creamapi.Converters
{
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;
}
private static string DlcListToString(List<SteamApp> value)
private static string DlcListToString(ObservableCollection<SteamApp> value)
{
var result = "";
value.ForEach(x => result += $"{x}\n");
//value.ForEach(x => result += $"{x}\n");
foreach (var steamApp in value) result += $"{steamApp}\n";
return result;
}
}

View File

@ -1,6 +1,4 @@
using auto_creamapi.Services;
using auto_creamapi.ViewModels;
using MvvmCross;
using MvvmCross.IoC;
using MvvmCross.ViewModels;

View File

@ -1,21 +0,0 @@
<Window x:Class="auto_creamapi.DownloadWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:auto_creamapi"
mc:Ignorable="d"
Title="Please wait..." Width="400" Height="200">
<Grid Margin="10,10,10,20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<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="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"
Minimum="0" Maximum="0.99" ValueChanged="ProgressBar_OnValueChanged" Value="0"/>
</Grid>
</Window>

View File

@ -1,32 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using auto_creamapi.Utils;
namespace auto_creamapi
{
/// <summary>
/// Interaction logic for DownloadWindow.xaml
/// </summary>
public partial class DownloadWindow
{
public DownloadWindow()
{
WindowStartupLocation = WindowStartupLocation.CenterScreen;
InitializeComponent();
}
private void ProgressBar_OnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
//MyLogger.Log.Information(ProgressBar.Value.ToString("N"));
}
}
}

View File

@ -1,6 +1,4 @@
using System.Windows;
using MvvmCross.Platforms.Wpf.Presenters.Attributes;
using MvvmCross.Platforms.Wpf.Views;
namespace auto_creamapi
{

View File

@ -0,0 +1,40 @@
using HttpProgress;
using MvvmCross.Plugin.Messenger;
namespace auto_creamapi.Messenger
{
public class ProgressMessage : MvxMessage
{
private readonly ICopyProgress _progress;
private double _percentProgress;
public ProgressMessage(object sender, string info, string filename, ICopyProgress progress) : base(sender)
{
Info = info;
Filename = filename;
_progress = progress;
}
public ProgressMessage(object sender, string info, string filename, double progress) : base(sender)
{
_progress = null;
Info = info;
Filename = filename;
PercentComplete = progress;
}
public string Info { get; }
public string Filename { get; }
public double PercentComplete
{
get => _progress?.PercentComplete ?? _percentProgress;
private set => _percentProgress = value;
}
// public long BytesTransferred => _progress.BytesTransferred;
// public long ExpectedBytes => _progress.ExpectedBytes;
// public long BytesPerSecond => _progress.BytesPerSecond;
// public TimeSpan TransferTime => _progress.TransferTime;
}
}

View File

@ -1,30 +1,23 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using auto_creamapi.Utils;
using IniParser;
using IniParser.Model;
using System.Collections.Generic;
namespace auto_creamapi.Models
{
public class CreamConfig
{
public CreamConfig()
{
DlcList = new List<SteamApp>();
}
public int AppId { get; set; }
public string Language { get; set; }
public bool UnlockAll { get; set; }
public bool ExtraProtection { get; set; }
public bool ForceOffline { get; set; }
public List<SteamApp> DlcList { get; set; }
}
public CreamConfig()
{
DlcList = new List<SteamApp>();
}
}
public sealed class CreamConfigModel
{
}
}

View File

@ -1,18 +1,14 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Threading.Tasks;
using auto_creamapi.Services;
using auto_creamapi.Utils;
namespace auto_creamapi.Models
{
internal class CreamDll
{
public readonly string Filename;
public readonly string OrigFilename;
public readonly string Hash;
public readonly string OrigFilename;
public CreamDll(string filename, string origFilename)
{
@ -30,8 +26,8 @@ namespace auto_creamapi.Models
}
}
}
public class CreamDllModel
{
}
}

View File

@ -1,16 +1,13 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using MvvmCross.ViewModels;
namespace auto_creamapi.Models
{
public class SteamApp
{
[JsonPropertyName("appid")]
public int AppId { get; set; }
[JsonPropertyName("appid")] public int AppId { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("name")] public string Name { get; set; }
public override string ToString()
{
@ -26,13 +23,11 @@ namespace auto_creamapi.Models
public class AppList
{
[JsonPropertyName("apps")]
public List<SteamApp> Apps { get; set; }
[JsonPropertyName("apps")] public List<SteamApp> Apps { get; set; }
}
public class SteamApps
{
[JsonPropertyName("applist")]
public AppList AppList { get; set; }
[JsonPropertyName("applist")] public AppList AppList { get; set; }
}
}

View File

@ -1,26 +0,0 @@
<Window x:Class="auto_creamapi.SearchResultWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="clr-namespace:auto_creamapi.Models"
mc:Ignorable="d"
Title="Search Results" Width="420" Height="540" MinWidth="420" MinHeight="540">
<Grid Margin="10,10,10,10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="Select a game..." HorizontalAlignment="Left" Margin="0,0,0,10" VerticalAlignment="Top"/>
<DataGrid Name="DgApps" Grid.Row="1" AutoGenerateColumns="False" IsReadOnly="True" SelectionMode="Single" d:DataContext="{d:DesignInstance models:SteamApp}" MouseDoubleClick="DgApps_OnMouseDoubleClick">
<DataGrid.Columns>
<DataGridTextColumn Header="AppID" Binding="{Binding AppId}"></DataGridTextColumn>
<DataGridTextColumn Header="Game Name" Binding="{Binding Name}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<Button Content="OK" HorizontalAlignment="Right" Margin="0,10,70,0" Grid.Row="2" VerticalAlignment="Top" Width="60" Click="OK_OnClick"/>
<Button Content="Cancel" HorizontalAlignment="Right" Margin="0,10,0,0" Grid.Row="2" VerticalAlignment="Top" Width="60" Click="Cancel_OnClick"/>
</Grid>
</Window>

View File

@ -4,6 +4,7 @@ using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AngleSharp.Dom;
using AngleSharp.Html.Parser;
@ -17,7 +18,10 @@ namespace auto_creamapi.Services
public interface ICacheService
{
public List<string> Languages { get; }
public void UpdateCache();
public Task Initialize();
//public Task UpdateCache();
public IEnumerable<SteamApp> GetListOfAppsByName(string name);
public SteamApp GetAppByName(string name);
public SteamApp GetAppById(int appid);
@ -28,43 +32,14 @@ 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 const string SpecialCharsRegex = "[^0-9a-zA-Z]+";
private List<SteamApp> _cache = new List<SteamApp>();
private readonly List<string> _languages = new List<string>(new[]
{
"arabic",
"bulgarian",
"schinese",
"tchinese",
"czech",
"danish",
"dutch",
"english",
"finnish",
"french",
"german",
"greek",
"hungarian",
"italian",
"japanese",
"koreana",
"norwegian",
"polish",
"portuguese",
"brazilian",
"romanian",
"russian",
"spanish",
"latam",
"swedish",
"thai",
"turkish",
"ukrainian",
"vietnamese"
});
/*private static readonly Lazy<CacheService> Lazy =
new Lazy<CacheService>(() => new CacheService());
@ -73,13 +48,18 @@ namespace auto_creamapi.Services
public CacheService()
{
Languages = _languages;
UpdateCache();
Languages = Misc.DefaultLanguages;
}
/*public async void Initialize()
{
//Languages = _defaultLanguages;
await UpdateCache();
}*/
public List<string> Languages { get; }
public void UpdateCache()
public async Task Initialize()
{
MyLogger.Log.Information("Updating cache...");
var updateNeeded = DateTime.Now.Subtract(File.GetLastWriteTimeUtc(CachePath)).TotalDays >= 1;
@ -89,20 +69,19 @@ namespace auto_creamapi.Services
MyLogger.Log.Information("Getting content from API...");
var client = new HttpClient();
var httpCall = client.GetAsync(SteamUri);
var response = httpCall.Result;
var response = await httpCall;
var readAsStringAsync = response.Content.ReadAsStringAsync();
var responseBody = readAsStringAsync.Result;
var responseBody = await readAsStringAsync;
MyLogger.Log.Information("Got content from API successfully. Writing to file...");
//var writeAllTextAsync = File.WriteAllTextAsync(CachePath, responseBody, Encoding.UTF8);
//writeAllTextAsync.RunSynchronously();
File.WriteAllText(CachePath, responseBody, Encoding.UTF8);
await File.WriteAllTextAsync(CachePath, responseBody, Encoding.UTF8);
cacheString = responseBody;
MyLogger.Log.Information("Cache written to file successfully.");
}
else
{
MyLogger.Log.Information("Cache already up to date!");
// ReSharper disable once MethodHasAsyncOverload
cacheString = File.ReadAllText(CachePath);
}
@ -122,7 +101,9 @@ namespace auto_creamapi.Services
public SteamApp GetAppByName(string name)
{
MyLogger.Log.Information($"Trying to get app {name}");
var app = _cache.Find(x => x.Name.ToLower().Equals(name.ToLower()));
var app = _cache.Find(x =>
Regex.Replace(x.Name, SpecialCharsRegex, "").ToLower()
.Equals(Regex.Replace(name, SpecialCharsRegex, "").ToLower()));
if (app != null) MyLogger.Log.Information($"Successfully got app {app}");
return app;
}
@ -194,10 +175,7 @@ namespace auto_creamapi.Services
var dlcId = element.GetAttribute("data-appid");
var dlcName = $"Unknown DLC {dlcId}";
var query3 = element.QuerySelectorAll("td");
if (query3 != null)
{
dlcName = query3[1].Text().Replace("\n", "").Trim();
}
if (query3 != null) dlcName = query3[1].Text().Replace("\n", "").Trim();
var dlcApp = new SteamApp {AppId = Convert.ToInt32(dlcId), Name = dlcName};
var i = dlcList.FindIndex(x => x.CompareId(dlcApp));
@ -222,7 +200,7 @@ namespace auto_creamapi.Services
}
else
{
MyLogger.Log.Error($"Could not get DLC: Invalid Steam App");
MyLogger.Log.Error("Could not get DLC: Invalid Steam App");
}
return dlcList;

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
@ -14,6 +15,7 @@ namespace auto_creamapi.Services
public interface ICreamConfigService
{
public CreamConfig Config { get; }
public void Initialize();
public void ReadFile(string configFilePath);
public void SaveFile();
@ -31,21 +33,31 @@ namespace auto_creamapi.Services
bool forceOffline,
List<SteamApp> dlcList);
public void SetConfigData(int appId,
string language,
bool unlockAll,
bool extraProtection,
bool forceOffline,
ObservableCollection<SteamApp> dlcList);
public bool ConfigExists();
}
public class CreamConfigService : ICreamConfigService
{
public CreamConfig Config { get; }
private string _configFilePath;
public CreamConfigService()
public CreamConfig Config { get; set; }
public void Initialize()
{
//await Task.Run(() =>
//{
//MyLogger.Log.Debug("CreamConfigService: init start");
Config = new CreamConfig();
ResetConfigData();
//MyLogger.Log.Debug("CreamConfigService: init end");
//});
}
public void ReadFile(string configFilePath)
@ -66,10 +78,8 @@ namespace auto_creamapi.Services
var dlcCollection = data["dlc"];
foreach (var item in dlcCollection)
{
//Config.DlcList.Add(int.Parse(item.KeyName), item.Value);
Config.DlcList.Add(new SteamApp{AppId = int.Parse(item.KeyName), Name = item.Value});
}
Config.DlcList.Add(new SteamApp {AppId = int.Parse(item.KeyName), Name = item.Value});
}
else
{
@ -99,16 +109,6 @@ namespace auto_creamapi.Services
parser.WriteFile(_configFilePath, data, Encoding.UTF8);
}
private void ResetConfigData()
{
Config.AppId = -1;
Config.Language = "";
Config.UnlockAll = false;
Config.ExtraProtection = false;
Config.ForceOffline = false;
Config.DlcList.Clear();
}
public void SetConfigData(int appId,
string language,
bool unlockAll,
@ -139,6 +139,36 @@ namespace auto_creamapi.Services
Config.DlcList = dlcList;
}
public void SetConfigData(int appId,
string language,
bool unlockAll,
bool extraProtection,
bool forceOffline,
ObservableCollection<SteamApp> dlcList)
{
Config.AppId = appId;
Config.Language = language;
Config.UnlockAll = unlockAll;
Config.ExtraProtection = extraProtection;
Config.ForceOffline = forceOffline;
Config.DlcList = new List<SteamApp>(dlcList);
}
public bool ConfigExists()
{
return File.Exists(_configFilePath);
}
private void ResetConfigData()
{
Config.AppId = -1;
Config.Language = "";
Config.UnlockAll = false;
Config.ExtraProtection = false;
Config.ForceOffline = false;
Config.DlcList.Clear();
}
private void SetDlcFromString(string dlcList)
{
Config.DlcList.Clear();
@ -149,10 +179,8 @@ namespace auto_creamapi.Services
{
var match = expression.Match(line);
if (match.Success)
{
Config.DlcList.Add(
new SteamApp{AppId = int.Parse(match.Groups["id"].Value), Name = match.Groups["name"].Value});
}
new SteamApp {AppId = int.Parse(match.Groups["id"].Value), Name = match.Groups["name"].Value});
}
}
/*private void SetDlcFromAppList(List<SteamApp> dlcList)
@ -171,22 +199,15 @@ namespace auto_creamapi.Services
$"ForceOffline: {Config.ForceOffline}, " +
$"DLC ({Config.DlcList.Count}):\n[\n";
if (Config.DlcList.Count > 0)
{
str = Config.DlcList.Aggregate(str, (current, x) => current + $" {x.AppId}={x.Name},\n");
/*foreach (var (key, value) in Config.DlcList)
{
str += $" {key}={value},\n";
}*/
}
str += "]";
return str;
}
public bool ConfigExists()
{
return File.Exists(_configFilePath);
}
}
}

View File

@ -11,8 +11,7 @@ namespace auto_creamapi.Services
public interface ICreamDllService
{
public string TargetPath { get; set; }
public void Initialize();
//public Task InitializeAsync();
public Task Initialize();
public void Save();
public void CheckIfDllExistsAtTarget();
public bool CreamApiApplied();
@ -20,28 +19,18 @@ namespace auto_creamapi.Services
public class CreamDllService : ICreamDllService
{
private readonly IDownloadCreamApiService _downloadService;
public string TargetPath { get; set; }
private readonly Dictionary<string, CreamDll> _creamDlls = new Dictionary<string, CreamDll>();
private static readonly string HashPath = Path.Combine(Directory.GetCurrentDirectory(), "cream_api.md5");
private const string X86Arch = "x86";
private const string X64Arch = "x64";
private static readonly string HashPath = Path.Combine(Directory.GetCurrentDirectory(), "cream_api.md5");
private bool _x86Exists;
private readonly Dictionary<string, CreamDll> _creamDlls = new Dictionary<string, CreamDll>();
private bool _x64Exists;
public CreamDllService(IDownloadCreamApiService downloadService)
{
_downloadService = downloadService;
}
private bool _x86Exists;
public Task InitializeAsync()
{
return Task.Run(Initialize);
}
public string TargetPath { get; set; }
public void Initialize()
public async Task Initialize()
{
MyLogger.Log.Debug("CreamDllService: Initialize begin");
@ -51,7 +40,8 @@ namespace auto_creamapi.Services
if (!File.Exists(HashPath))
{
MyLogger.Log.Information("Writing md5sum file...");
File.WriteAllLines(HashPath, new[]
await File.WriteAllLinesAsync(HashPath,
new[]
{
$"{_creamDlls[X86Arch].Hash} {_creamDlls[X86Arch].Filename}",
$"{_creamDlls[X64Arch].Hash} {_creamDlls[X64Arch].Filename}"
@ -67,6 +57,23 @@ namespace auto_creamapi.Services
if (_x64Exists) CopyDll(X64Arch);
}
public void CheckIfDllExistsAtTarget()
{
var x86file = Path.Combine(TargetPath, "steam_api.dll");
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}");
}
public bool CreamApiApplied()
{
var a = CreamApiApplied("x86");
var b = CreamApiApplied("x64");
return a | b;
}
private void CopyDll(string arch)
{
var sourceSteamApiDll = _creamDlls[arch].Filename;
@ -84,30 +91,13 @@ namespace auto_creamapi.Services
File.Copy(sourceSteamApiDll, targetSteamApiDll, true);
}
public void CheckIfDllExistsAtTarget()
{
var x86file = Path.Combine(TargetPath, "steam_api.dll");
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}");
}
public bool CreamApiApplied(string arch)
{
bool a = File.Exists(Path.Combine(TargetPath, _creamDlls[arch].OrigFilename));
bool b = GetHash(Path.Combine(TargetPath, _creamDlls[arch].Filename)).Equals(_creamDlls[arch].Hash);
var a = File.Exists(Path.Combine(TargetPath, _creamDlls[arch].OrigFilename));
var b = GetHash(Path.Combine(TargetPath, _creamDlls[arch].Filename)).Equals(_creamDlls[arch].Hash);
return a & b;
}
public bool CreamApiApplied()
{
bool a = CreamApiApplied("x86");
bool b = CreamApiApplied("x64");
return a | b;
}
private string GetHash(string filename)
{
if (File.Exists(filename))
@ -118,10 +108,8 @@ namespace auto_creamapi.Services
.ToString(md5.ComputeHash(stream))
.Replace("-", string.Empty);
}
else
{
return "";
}
}
}
}

View File

@ -6,9 +6,10 @@ using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Threading;
using auto_creamapi.Messenger;
using auto_creamapi.Utils;
using HttpProgress;
using MvvmCross.Plugin.Messenger;
using SharpCompress.Archives;
using SharpCompress.Common;
using SharpCompress.Readers;
@ -17,73 +18,26 @@ namespace auto_creamapi.Services
{
public interface IDownloadCreamApiService
{
public void Initialize();
// public Task InitializeAsync();
public Task DownloadAndExtract(string username, string password);
/*public void Initialize();
public Task InitializeAsync();*/
public Task<string> Download(string username, string password);
public void Extract(string filename);
}
public class DownloadCreamApiService : IDownloadCreamApiService
{
private const string ArchivePassword = "cs.rin.ru";
private static string _filename;
//private static DownloadWindow _wnd;
public DownloadCreamApiService()
//private string _filename;
private readonly IMvxMessenger _messenger;
//private DownloadWindow _wnd;
public DownloadCreamApiService(IMvxMessenger messenger)
{
_messenger = messenger;
}
public void Initialize()
{
MyLogger.Log.Debug("DownloadCreamApiService: Initialize begin");
if (File.Exists("steam_api.dll") && File.Exists("steam_api64.dll"))
{
MyLogger.Log.Information("Skipping download...");
}
else
{
MyLogger.Log.Information("Missing files, trying to download...");
DownloadAndExtract(Secrets.ForumUsername, Secrets.ForumPassword).Start();
}
//await creamDllService.InitializeAsync();
MyLogger.Log.Debug("DownloadCreamApiService: Initialize end");
}
public async Task InitializeAsync()
{
MyLogger.Log.Debug("DownloadCreamApiService: Initialize begin");
if (File.Exists("steam_api.dll") && File.Exists("steam_api64.dll"))
{
MyLogger.Log.Information("Skipping download...");
}
else
{
MyLogger.Log.Information("Missing files, trying to download...");
var downloadAndExtract = DownloadAndExtract(Secrets.ForumUsername, Secrets.ForumPassword);
await downloadAndExtract;
downloadAndExtract.Wait();
}
//await creamDllService.InitializeAsync();
MyLogger.Log.Debug("DownloadCreamApiService: Initialize end");
}
public async Task DownloadAndExtract(string username, string password)
{
MyLogger.Log.Debug("DownloadAndExtract");
//_wnd = new DownloadWindow();
//_wnd.Show();
var download = Download(username, password);
await download;
download.Wait();
/*var extract = Extract();
await extract;
extract.Wait();*/
var extract = Task.Run(Extract);
await extract;
extract.Wait();
//_wnd.Close();
}
private static async Task Download(string username, string password)
public async Task<string> Download(string username, string password)
{
MyLogger.Log.Debug("Download");
var container = new CookieContainer();
@ -125,69 +79,36 @@ namespace auto_creamapi.Services
}
}
/*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))
//filename = filename;
if (File.Exists(filename))
{
MyLogger.Log.Information($"{_filename} already exists, skipping download...");
return;
MyLogger.Log.Information($"{filename} already exists, skipping download...");
return filename;
}
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);
x => _messenger.Publish(new ProgressMessage(this, "Downloading...", filename, x)));
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);*/
}
_messenger.Publish(new ProgressMessage(this, "Downloading...", filename, 1.0));
MyLogger.Log.Information("Download done.");
return filename;
}
private static void Extract()
public void Extract(string filename)
{
MyLogger.Log.Debug("Extract");
MyLogger.Log.Information("Start extraction...");
MyLogger.Log.Information($@"Start extraction of ""{filename}""...");
var options = new ReaderOptions {Password = ArchivePassword};
var archive = ArchiveFactory.Open(_filename, options);
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);*/
_messenger.Publish(new ProgressMessage(this, "Extracting...", filename, 1.0));
foreach (var entry in archive.Entries)
{
// ReSharper disable once InvertIf
if (!entry.IsDirectory && expression1.IsMatch(entry.Key))
{
@ -198,7 +119,6 @@ namespace auto_creamapi.Services
Overwrite = true
});
}
}
MyLogger.Log.Information("Extraction done!");
}

View File

@ -0,0 +1,40 @@
using System.Collections.Generic;
namespace auto_creamapi.Utils
{
public class Misc
{
public static readonly List<string> DefaultLanguages = new List<string>(new[]
{
"arabic",
"bulgarian",
"schinese",
"tchinese",
"czech",
"danish",
"dutch",
"english",
"finnish",
"french",
"german",
"greek",
"hungarian",
"italian",
"japanese",
"koreana",
"norwegian",
"polish",
"portuguese",
"brazilian",
"romanian",
"russian",
"spanish",
"latam",
"swedish",
"thai",
"turkish",
"ukrainian",
"vietnamese"
});
}
}

View File

@ -0,0 +1,87 @@
using System.Threading.Tasks;
using auto_creamapi.Messenger;
using auto_creamapi.Services;
using auto_creamapi.Utils;
using MvvmCross.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 string _filename;
private string _info;
private double _progress;
public DownloadViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService,
IDownloadCreamApiService download, IMvxMessenger messenger) : base(logProvider, navigationService)
{
_navigationService = navigationService;
_download = download;
_token = messenger.Subscribe<ProgressMessage>(OnProgressMessage);
MyLogger.Log.Debug(messenger.CountSubscriptionsFor<ProgressMessage>().ToString());
}
public string InfoLabel
{
get => _info;
set
{
_info = value;
RaisePropertyChanged(() => InfoLabel);
}
}
public string FilenameLabel
{
get => _filename;
set
{
_filename = value;
RaisePropertyChanged(() => FilenameLabel);
}
}
public double Progress
{
get => _progress;
set
{
_progress = value;
RaisePropertyChanged(() => Progress);
RaisePropertyChanged(() => ProgressPercent);
}
}
public string ProgressPercent => _progress.ToString("P2");
public override async Task Initialize()
{
await base.Initialize();
InfoLabel = "Please wait...";
FilenameLabel = "";
Progress = 0.0;
var download = _download.Download(Secrets.ForumUsername, Secrets.ForumPassword);
var filename = await download;
/*var extract = _download.Extract(filename);
await extract;*/
await Task.Run(() => _download.Extract(filename));
_token.Dispose();
await _navigationService.Close(this);
}
private void OnProgressMessage(ProgressMessage obj)
{
//MyLogger.Log.Debug($"{obj.Filename}: {obj.BytesTransferred}");
InfoLabel = obj.Info;
FilenameLabel = obj.Filename;
Progress = obj.PercentComplete;
}
}
}

View File

@ -3,218 +3,68 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Threading;
using auto_creamapi.Models;
using auto_creamapi.Services;
using auto_creamapi.Utils;
using auto_creamapi.Views;
using Microsoft.Win32;
using MvvmCross.Commands;
using MvvmCross.Navigation;
using MvvmCross.ViewModels;
namespace auto_creamapi.ViewModels
{
public class MainViewModel : MvxViewModel
{
private const string DefaultLanguageSelection = "english";
private readonly ICacheService _cache;
private readonly ICreamConfigService _config;
private readonly ICreamDllService _dll;
private readonly IDownloadCreamApiService _download;
private bool _mainWindowEnabled;
private string _dllPath;
private string _gameName;
private readonly IMvxNavigationService _navigationService;
private int _appId;
private string _lang;
private bool _offline;
private bool _extraprotection;
private bool _unlockall;
private bool _useSteamDb;
private bool _configExists;
private ObservableCollection<SteamApp> _dlcs;
private bool _dllApplied;
private bool _configExists;
private string _status;
private string _dllPath;
private bool _extraprotection;
private string _gameName;
private string _lang;
private ObservableCollection<string> _languages;
private const string DefaultLanguageSelection = "english";
private const string DlcRegexPattern = @"(?<id>.*) *= *(?<name>.*)";
//private readonly IDownloadCreamApiService _download;
private bool _mainWindowEnabled;
private bool _offline;
private string _status;
private bool _unlockall;
private bool _useSteamDb;
//private const string DlcRegexPattern = @"(?<id>.*) *= *(?<name>.*)";
public MainViewModel(ICacheService cache, ICreamConfigService config, ICreamDllService dll,
IDownloadCreamApiService download)
IMvxNavigationService navigationService)
{
_navigationService = navigationService;
_cache = cache;
_config = config;
_dll = dll;
_download = download;
}
public override async Task Initialize()
{
await base.Initialize();
Languages = new ObservableCollection<string>(_cache.Languages);
ResetForm();
_download.Initialize();
_dll.Initialize();
Lang = DefaultLanguageSelection;
UseSteamDb = true;
MainWindowEnabled = true;
Status = "Ready.";
//_download = download;
}
// // COMMANDS // //
public IMvxCommand OpenFileCommand => new MvxCommand(OpenFile);
private void OpenFile()
{
Status = "Waiting for file...";
var dialog = new OpenFileDialog
{
Filter = "SteamAPI DLL|steam_api.dll;steam_api64.dll|" +
"All files (*.*)|*.*",
Multiselect = false,
Title = "Select SteamAPI DLL..."
};
if (dialog.ShowDialog() == true)
{
var filePath = dialog.FileName;
DllPath = filePath;
var dirPath = Path.GetDirectoryName(filePath);
if (dirPath != null)
{
_config.ReadFile(Path.Combine(dirPath, "cream_api.ini"));
ResetForm();
_dll.TargetPath = dirPath;
_dll.CheckIfDllExistsAtTarget();
CheckExistence();
Status = "Ready.";
}
}
}
public IMvxCommand SearchCommand => new MvxCommand(Search);
private void Search()
{
var app = _cache.GetAppByName(GameName);
if (app != null)
{
GameName = app.Name;
AppId = app.AppId;
}
/*else
{
var listOfAppsByName = _cache.GetListOfAppsByName(GameName);
var searchWindow = new SearchResultWindow(listOfAppsByName);
searchWindow.Show();
}*/
}
public IMvxCommand SearchCommand => new MvxAsyncCommand(async () => await Search()); //Command(Search);
public IMvxCommand GetListOfDlcCommand => new MvxAsyncCommand(GetListOfDlc);
private async Task GetListOfDlc()
{
Status = "Trying to get DLC...";
if (AppId > 0)
{
var app = new SteamApp() {AppId = AppId, Name = GameName};
var task = _cache.GetListOfDlc(app, UseSteamDb);
MainWindowEnabled = false;
var listOfDlc = await task;
var result = "";
if (task.IsCompletedSuccessfully)
{
listOfDlc.Sort((app1, app2) => app1.AppId.CompareTo(app2.AppId));
listOfDlc.ForEach(x => result += $"{x.AppId}={x.Name}\n");
Dlcs = result;
Status = $"Got DLC for AppID {AppId}";
}
else
{
Status = $"Could not get DLC for AppID {AppId}";
}
MainWindowEnabled = true;
}
else
{
Status = $"Could not get DLC for AppID {AppId}";
MyLogger.Log.Error($"GetListOfDlc: Invalid AppID {AppId}");
}
}
public IMvxCommand SaveCommand => new MvxCommand(Save);
private void Save()
{
Status = "Saving...";
_config.SetConfigData(
AppId,
Lang,
Unlockall,
Extraprotection,
Offline,
Dlcs
);
_config.SaveFile();
_dll.Save();
CheckExistence();
Status = "Saving successful.";
}
public IMvxCommand ResetFormCommand => new MvxCommand(ResetForm);
private void ResetForm()
{
AppId = _config.Config.AppId;
Lang = _config.Config.Language;
Unlockall = _config.Config.UnlockAll;
Extraprotection = _config.Config.ExtraProtection;
Offline = _config.Config.ForceOffline;
var configDlcList = _config.Config.DlcList;
var result = "";
foreach (var x in configDlcList)
{
result += $"{x.AppId}={x.Name}\n";
}
Dlcs = result;
}
public IMvxCommand GoToForumThreadCommand => new MvxCommand(GoToForumThread);
private void GoToForumThread()
{
Status = "Opening URL...";
if (AppId > 0)
{
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";
var uri = new Uri(destinationUrl);
var process = new ProcessStartInfo(uri.AbsoluteUri)
{
UseShellExecute = true
};
Process.Start(process);
}
else
{
MyLogger.Log.Error($"OpenURL: Invalid AppID {AppId}");
Status = $"Could not open URL: Invalid AppID {AppId}";
}
}
private void CheckExistence()
{
DllApplied = _dll.CreamApiApplied();
ConfigExists = _config.ConfigExists();
}
// // ATTRIBUTES // //
public bool MainWindowEnabled
@ -259,12 +109,6 @@ namespace auto_creamapi.ViewModels
}
}
private void SetNameById()
{
var appById = _cache.GetAppById(_appId);
GameName = appById != null ? appById.Name : "";
}
public string Lang
{
get => _lang;
@ -316,53 +160,14 @@ namespace auto_creamapi.ViewModels
}
}
/*public List<SteamApp> Dlcs
public ObservableCollection<SteamApp> Dlcs
{
get => _dlcs;
set
{
_dlcs = value;
RaisePropertyChanged(Dlcs);
MyLogger.Log.Debug($"Dlcs: {value}");
RaisePropertyChanged(() => Dlcs);
}
}*/
public string Dlcs
{
get => DlcListToString(_dlcs);
set
{
_dlcs = StringToDlcList(value);
RaisePropertyChanged();
//MyLogger.Log.Debug($"Dlcs: {DlcListToString(_dlcs)}");
}
}
private static ObservableCollection<SteamApp> StringToDlcList(string value)
{
var result = new List<SteamApp>();
var expression = new Regex(@"(?<id>.*) *= *(?<name>.*)");
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 new ObservableCollection<SteamApp>(result);
}
private static string DlcListToString(IEnumerable<SteamApp> value)
{
return value.Aggregate("", (current, steamApp) => current + $"{steamApp}\n");
}
public bool DllApplied
@ -404,5 +209,179 @@ namespace auto_creamapi.ViewModels
RaisePropertyChanged(() => Languages);
}
}
public override async Task Initialize()
{
_config.Initialize();
/*await base.Initialize();
await _cache.Initialize();
if (!File.Exists("steam_api.dll") | !File.Exists("steam_api64.dll"))
await _navigationService.Navigate<DownloadViewModel>();
await _dll.Initialize();*/
var tasks = new List<Task> {base.Initialize(), _cache.Initialize()};
if (!File.Exists("steam_api.dll") | !File.Exists("steam_api64.dll"))
tasks.Add(_navigationService.Navigate<DownloadViewModel>());
tasks.Add(_dll.Initialize());
await Task.WhenAll(tasks);
Languages = new ObservableCollection<string>(_cache.Languages);
ResetForm();
Lang = DefaultLanguageSelection;
UseSteamDb = true;
MainWindowEnabled = true;
Status = "Ready.";
}
private void OpenFile()
{
Status = "Waiting for file...";
var dialog = new OpenFileDialog
{
Filter = "SteamAPI DLL|steam_api.dll;steam_api64.dll|" +
"All files (*.*)|*.*",
Multiselect = false,
Title = "Select SteamAPI DLL..."
};
if (dialog.ShowDialog() == true)
{
var filePath = dialog.FileName;
DllPath = filePath;
var dirPath = Path.GetDirectoryName(filePath);
if (dirPath != null)
{
_config.ReadFile(Path.Combine(dirPath, "cream_api.ini"));
ResetForm();
_dll.TargetPath = dirPath;
_dll.CheckIfDllExistsAtTarget();
CheckExistence();
Status = "Ready.";
}
}
else
{
Status = "File selection canceled.";
}
}
private async Task Search()
{
if (!string.IsNullOrEmpty(GameName))
{
var app = _cache.GetAppByName(GameName);
if (app != null)
{
GameName = app.Name;
AppId = app.AppId;
}
else
{
var navigate = _navigationService.Navigate<SearchResultViewModel, IEnumerable<SteamApp>, SteamApp>(
_cache.GetListOfAppsByName(GameName));
await navigate;
var navigateResult = navigate.Result;
if (navigateResult != null)
{
GameName = navigateResult.Name;
AppId = navigateResult.AppId;
}
}
}
else
{
MyLogger.Log.Warning("Empty game name, cannot initiate search!");
}
}
private async Task GetListOfDlc()
{
Status = "Trying to get DLC...";
if (AppId > 0)
{
var app = new SteamApp {AppId = AppId, Name = GameName};
var task = _cache.GetListOfDlc(app, UseSteamDb);
MainWindowEnabled = false;
var listOfDlc = await task;
if (task.IsCompletedSuccessfully)
{
listOfDlc.Sort((app1, app2) => app1.AppId.CompareTo(app2.AppId));
Dlcs = new ObservableCollection<SteamApp>(listOfDlc);
Status = $"Got DLC for AppID {AppId}";
}
else
{
Status = $"Could not get DLC for AppID {AppId}";
}
MainWindowEnabled = true;
}
else
{
Status = $"Could not get DLC for AppID {AppId}";
MyLogger.Log.Error($"GetListOfDlc: Invalid AppID {AppId}");
}
}
private void Save()
{
Status = "Saving...";
_config.SetConfigData(
AppId,
Lang,
Unlockall,
Extraprotection,
Offline,
Dlcs
);
_config.SaveFile();
_dll.Save();
CheckExistence();
Status = "Saving successful.";
}
private void ResetForm()
{
AppId = _config.Config.AppId;
Lang = _config.Config.Language;
Unlockall = _config.Config.UnlockAll;
Extraprotection = _config.Config.ExtraProtection;
Offline = _config.Config.ForceOffline;
Dlcs = new ObservableCollection<SteamApp>(_config.Config.DlcList);
Status = "Changes have been reset.";
}
private void GoToForumThread()
{
Status = "Opening URL...";
if (AppId > 0)
{
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";
var uri = new Uri(destinationUrl);
var process = new ProcessStartInfo(uri.AbsoluteUri)
{
UseShellExecute = true
};
Process.Start(process);
}
else
{
MyLogger.Log.Error($"OpenURL: Invalid AppID {AppId}");
Status = $"Could not open URL: Invalid AppID {AppId}";
}
}
private void CheckExistence()
{
DllApplied = _dll.CreamApiApplied();
ConfigExists = _config.ConfigExists();
}
private void SetNameById()
{
var appById = _cache.GetAppById(_appId);
GameName = appById != null ? appById.Name : "";
}
}
}

View File

@ -0,0 +1,80 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using auto_creamapi.Models;
using auto_creamapi.Utils;
using MvvmCross.Commands;
using MvvmCross.Logging;
using MvvmCross.Navigation;
using MvvmCross.ViewModels;
namespace auto_creamapi.ViewModels
{
public class SearchResultViewModel : MvxNavigationViewModel<IEnumerable<SteamApp>>,
IMvxViewModel<IEnumerable<SteamApp>, SteamApp>
{
private readonly IMvxNavigationService _navigationService;
private IEnumerable<SteamApp> _steamApps;
/*public override async Task Initialize()
{
await base.Initialize();
}*/
public SearchResultViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService) : base(
logProvider, navigationService)
{
_navigationService = navigationService;
}
public IEnumerable<SteamApp> Apps
{
get => _steamApps;
set
{
_steamApps = value;
RaisePropertyChanged(() => Apps);
}
}
public SteamApp Selected
{
get;
set;
//RaisePropertyChanged(Selected);
}
public IMvxCommand SaveCommand => new MvxAsyncCommand(Save);
public IMvxCommand CloseCommand => new MvxCommand(Close);
public override void Prepare(IEnumerable<SteamApp> parameter)
{
Apps = parameter;
}
public TaskCompletionSource<object> CloseCompletionSource { get; set; }
public override void ViewDestroy(bool viewFinishing = true)
{
if (viewFinishing && CloseCompletionSource != null && !CloseCompletionSource.Task.IsCompleted &&
!CloseCompletionSource.Task.IsFaulted)
CloseCompletionSource?.TrySetCanceled();
base.ViewDestroy(viewFinishing);
}
private async Task Save()
{
if (Selected != null)
{
MyLogger.Log.Information($"Successfully got app {Selected}");
await _navigationService.Close(this, Selected);
}
}
private void Close()
{
//throw new System.NotImplementedException();
_navigationService.Close(this);
}
}
}

View File

@ -0,0 +1,27 @@
<views:MvxWindow x:Class="auto_creamapi.Views.DownloadView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf"
xmlns:viewModels="clr-namespace:auto_creamapi.ViewModels"
d:DataContext="{d:DesignInstance Type=viewModels:DownloadViewModel}"
mc:Ignorable="d"
Title="Please wait..." Width="400" Height="200">
<Grid Margin="10,10,10,20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Content="{Binding InfoLabel}" Name="InfoLabel" HorizontalAlignment="Left" Margin="0,0,0,0"
VerticalAlignment="Top" />
<Label Content="{Binding FilenameLabel}" Name="FilenameLabel" HorizontalAlignment="Left" Margin="0,0,0,0"
VerticalAlignment="Top" Grid.Row="1" />
<Label Content="{Binding ProgressPercent}" 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"
Minimum="0" Maximum="1.0" Value="{Binding Progress}" />
</Grid>
</views:MvxWindow>

View File

@ -0,0 +1,23 @@
using System.Windows;
using MvvmCross.Platforms.Wpf.Presenters.Attributes;
namespace auto_creamapi.Views
{
/// <summary>
/// Interaction logic for DownloadWindow.xaml
/// </summary>
[MvxWindowPresentation(Identifier = nameof(DownloadView), Modal = true)]
public partial class DownloadView
{
public DownloadView()
{
WindowStartupLocation = WindowStartupLocation.CenterScreen;
InitializeComponent();
}
/*private void ProgressBar_OnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
//MyLogger.Log.Information(ProgressBar.Value.ToString("N"));
}*/
}
}

View File

@ -11,73 +11,102 @@
xmlns:converters="clr-namespace:auto_creamapi.Converters"
mc:Ignorable="d">
<views:MvxWpfView.Resources>
<converters:ListOfDLcToStringConverter x:Key="DlcConv"/>
<converters:ListOfDLcToStringNativeConverter x:Key="DlcConv" />
</views:MvxWpfView.Resources>
<Grid IsEnabled="{Binding MainWindowEnabled, Mode=TwoWay}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<wcl:WatermarkTextBox x:Name="DllPath" Text="{Binding DllPath}" Watermark="Path to game's steam_api(64).dll..." Margin="10,11,55,0" TextWrapping="NoWrap" VerticalAlignment="Top" Padding="0" Grid.Row="0" IsReadOnly="True" IsReadOnlyCaretVisible="True">
<wcl:WatermarkTextBox x:Name="DllPath" Text="{Binding DllPath}" Watermark="Path to game's steam_api(64).dll..."
Margin="10,11,55,0" TextWrapping="NoWrap" VerticalAlignment="Top" Padding="0"
Grid.Row="0" IsReadOnly="True" IsReadOnlyCaretVisible="True">
<!--MouseDoubleClick="{Binding Path=OpenFileCommand}"-->
<wcl:WatermarkTextBox.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding OpenFileCommand}"></MouseBinding>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding OpenFileCommand}" />
</wcl:WatermarkTextBox.InputBindings>
</wcl:WatermarkTextBox>
<Button Content="&#xE1A5;" HorizontalAlignment="Right" Margin="0,10,10,0" VerticalAlignment="Top" FontFamily="Segoe UI Symbol" Width="40" Command="{Binding OpenFileCommand}" ToolTip="Select DLL file." Grid.Row="0"/>
<wcl:WatermarkTextBox Text="{Binding GameName, Mode=TwoWay}" x:Name="Game" Margin="10,10,180,0" Watermark="Game Name" TextWrapping="Wrap" VerticalAlignment="Top" Padding="0" Grid.Row="1"/>
<Button Content="&#xE11A;" HorizontalAlignment="Right" Margin="0,9,135,0" VerticalAlignment="Top" FontFamily="Segoe UI Symbol" Width="40" Command="{Binding SearchCommand}" ToolTip="Find AppID." Grid.Row="1"/>
<wcl:WatermarkTextBox Text="{Binding AppId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="AppId" HorizontalAlignment="Right" Margin="0,10,10,0" Watermark="AppID" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Padding="0" Grid.Row="1" />
<Button Content="&#xE1A5;" HorizontalAlignment="Right" Margin="0,10,10,0" VerticalAlignment="Top"
FontFamily="Segoe UI Symbol" Width="40" Command="{Binding OpenFileCommand}" ToolTip="Select DLL file."
Grid.Row="0" />
<wcl:WatermarkTextBox Text="{Binding GameName, Mode=TwoWay}" x:Name="Game" Margin="10,10,180,0"
Watermark="Game Name" TextWrapping="Wrap" VerticalAlignment="Top" Padding="0"
Grid.Row="1" />
<Button Content="&#xE11A;" HorizontalAlignment="Right" Margin="0,9,135,0" VerticalAlignment="Top"
FontFamily="Segoe UI Symbol" Width="40" Command="{Binding SearchCommand}" ToolTip="Find AppID."
Grid.Row="1" />
<wcl:WatermarkTextBox Text="{Binding AppId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="AppId"
HorizontalAlignment="Right" Margin="0,10,10,0" Watermark="AppID" TextWrapping="Wrap"
VerticalAlignment="Top" Width="120" Padding="0" Grid.Row="1" />
<TextBlock Grid.Row="2" Margin="10,10,10,0">
<Hyperlink Command="{Binding GoToForumThreadCommand}">Search for cs.rin.ru thread</Hyperlink>
</TextBlock>
<ComboBox x:Name="Lang" ItemsSource="{Binding Path=Languages}" SelectedItem="{Binding Path=Lang, Mode=TwoWay}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="120" Grid.Row="3"/>
<CheckBox x:Name="ForceOffline" Content="Force offline mode" IsChecked="{Binding Offline, Mode=TwoWay}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" ToolTip="offlinemode" Grid.Row="4"/>
<CheckBox x:Name="ExtraProtection" Content="Try to bypass game-specific protection" IsChecked="{Binding Extraprotection, Mode=TwoWay}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" ToolTip="extraprotection" Grid.Row="5"/>
<ComboBox x:Name="Lang" ItemsSource="{Binding Path=Languages}" SelectedItem="{Binding Path=Lang, Mode=TwoWay}"
HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="120" Grid.Row="3" />
<CheckBox x:Name="ForceOffline" Content="Force offline mode" IsChecked="{Binding Offline, Mode=TwoWay}"
HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" ToolTip="offlinemode"
Grid.Row="4" />
<CheckBox x:Name="ExtraProtection" Content="Try to bypass game-specific protection"
IsChecked="{Binding Extraprotection, Mode=TwoWay}" HorizontalAlignment="Left" Margin="10,10,0,0"
VerticalAlignment="Top" ToolTip="extraprotection" Grid.Row="5" />
<Grid Margin="10,10,10,0" Grid.Row="6">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<GroupBox Header="DLC" Grid.Row="0" VerticalAlignment="Stretch">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<CheckBox x:Name="UnlockAll" Content="Unlock all DLCs (if possible)" IsChecked="{Binding Unlockall, Mode=TwoWay}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" ToolTip="unlockall"/>
<CheckBox x:Name="SteamDb" Content="Additionally use SteamDB for DLCs" IsChecked="{Binding UseSteamDb, Mode=TwoWay}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Grid.Row="1"/>
<CheckBox x:Name="UnlockAll" Content="Unlock all DLCs (if possible)"
IsChecked="{Binding Unlockall, Mode=TwoWay}" HorizontalAlignment="Left"
Margin="10,10,0,0" VerticalAlignment="Top" ToolTip="unlockall" />
<CheckBox x:Name="SteamDb" Content="Additionally use SteamDB for DLCs"
IsChecked="{Binding UseSteamDb, Mode=TwoWay}" HorizontalAlignment="Left"
Margin="10,10,0,0" VerticalAlignment="Top" Grid.Row="1" />
<!-- Text="{Binding Dlcs, Converter={StaticResource DlcConv}, Mode=TwoWay}"-->
<!-- Text="{Binding DlcsString, Mode=TwoWay}"-->
<wcl:WatermarkTextBox x:Name="ListOfDlcs" Text="{Binding Dlcs, Mode=TwoWay}" Margin="10,10,10,0" Watermark="List of DLCs...&#xA;0000 = DLC Name" TextWrapping="Wrap" AcceptsReturn="True" VerticalScrollBarVisibility="Visible" Padding="0" FontFamily="./#Courier Prime" Grid.Row="2"/>
<Button Content="Get DLCs for AppID" Margin="0,10,10,10" Height="19.96" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="108" Command="{Binding GetListOfDlcCommand}" Grid.Row="3"/>
<wcl:WatermarkTextBox x:Name="ListOfDlcs"
Text="{Binding Dlcs, Converter={StaticResource DlcConv}, Mode=TwoWay}"
Margin="10,10,10,0" Watermark="List of DLCs...&#xA;0000 = DLC Name"
TextWrapping="Wrap" AcceptsReturn="True"
VerticalScrollBarVisibility="Visible" Padding="0"
FontFamily="./#Courier Prime" Grid.Row="2" />
<Button Content="Get DLCs for AppID" Margin="0,10,10,10" Height="19.96" HorizontalAlignment="Right"
VerticalAlignment="Bottom" Width="108" Command="{Binding GetListOfDlcCommand}" Grid.Row="3" />
</Grid>
</GroupBox>
<GroupBox Header="Status" Grid.Row="1" VerticalAlignment="Bottom" IsEnabled="False">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<CheckBox x:Name="CreamApiApplied" Content="CreamAPI DLL applied" Margin="10,10,0,10" Grid.Column="0" IsChecked="{Binding DllApplied, Mode=TwoWay}"/>
<CheckBox x:Name="ConfigExists" Content="CreamAPI Config exists" Margin="10,10,0,10" Grid.Column="1" IsChecked="{Binding ConfigExists, Mode=TwoWay}"/>
<CheckBox x:Name="CreamApiApplied" Content="CreamAPI DLL applied" Margin="10,10,0,10"
Grid.Column="0" IsChecked="{Binding DllApplied, Mode=TwoWay}" />
<CheckBox x:Name="ConfigExists" Content="CreamAPI Config exists" Margin="10,10,0,10"
Grid.Column="1" IsChecked="{Binding ConfigExists, Mode=TwoWay}" />
</Grid>
</GroupBox>
</Grid>
<Button Content="Save" Command="{Binding SaveCommand}" Margin="0,10,55,10" HorizontalAlignment="Right" Width="40" Height="20" VerticalAlignment="Bottom" Grid.Row="7"/>
<Button Content="Reset" Command="{Binding ResetFormCommand}" Margin="0,10,10,10" Height="20" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="40" Grid.Row="7"/>
<Button Content="Save" Command="{Binding SaveCommand}" Margin="0,10,55,10" HorizontalAlignment="Right"
Width="40" Height="20" VerticalAlignment="Bottom" Grid.Row="7" />
<Button Content="Reset" Command="{Binding ResetFormCommand}" Margin="0,10,10,10" Height="20"
VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="40" Grid.Row="7" />
<StatusBar Grid.Row="8">
<StatusBarItem Height="30" Margin="0,0,0,0">
<TextBlock x:Name="Status" Text="{Binding Status, Mode=TwoWay}"/>
<TextBlock x:Name="Status" Text="{Binding Status, Mode=TwoWay}" />
</StatusBarItem>
</StatusBar>
</Grid>

View File

@ -0,0 +1,34 @@
<views:MvxWindow x:Class="auto_creamapi.Views.SearchResultView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf"
xmlns:viewModels="clr-namespace:auto_creamapi.ViewModels"
d:DataContext="{d:DesignInstance Type=viewModels:SearchResultViewModel}"
mc:Ignorable="d"
Title="Search Results" Width="420" Height="540" MinWidth="420" MinHeight="540">
<Grid Margin="10,10,10,10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Content="Select a game..." HorizontalAlignment="Left" Margin="0,0,0,10" VerticalAlignment="Top" />
<!-- d:DataContext="{d:DesignInstance models:SteamApp}" MouseDoubleClick="DgApps_OnMouseDoubleClick" -->
<DataGrid Name="DgApps" Grid.Row="1" AutoGenerateColumns="False" IsReadOnly="True" SelectionMode="Single"
ItemsSource="{Binding Apps}" SelectedItem="{Binding Selected}">
<DataGrid.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding SaveCommand}" />
</DataGrid.InputBindings>
<DataGrid.Columns>
<DataGridTextColumn Header="AppID" Binding="{Binding AppId}" />
<DataGridTextColumn Header="Game Name" Binding="{Binding Name}" />
</DataGrid.Columns>
</DataGrid>
<Button Content="OK" Command="{Binding SaveCommand}" HorizontalAlignment="Right" Margin="0,10,70,0"
Grid.Row="2" VerticalAlignment="Top" Width="60" />
<Button Content="Cancel" Command="{Binding CloseCommand}" HorizontalAlignment="Right" Margin="0,10,0,0"
Grid.Row="2" VerticalAlignment="Top" Width="60" />
</Grid>
</views:MvxWindow>

View File

@ -1,35 +1,20 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using auto_creamapi.Models;
using auto_creamapi.Utils;
using NinjaNye.SearchExtensions;
using NinjaNye.SearchExtensions.Models;
using MvvmCross.Platforms.Wpf.Presenters.Attributes;
namespace auto_creamapi
namespace auto_creamapi.Views
{
/// <summary>
/// Interaction logic for SearchResultWindow.xaml
/// </summary>
public partial class SearchResultWindow
[MvxWindowPresentation(Identifier = nameof(SearchResultView), Modal = false)]
public partial class SearchResultView
{
public SearchResultWindow(IEnumerable<SteamApp> list)
public SearchResultView()
{
InitializeComponent();
DgApps.ItemsSource = list;
//DgApps.ItemsSource = list;
}
private void OK_OnClick(object sender, RoutedEventArgs e)
/*private void OK_OnClick(object sender, RoutedEventArgs e)
{
GetSelectedApp();
}
@ -58,6 +43,6 @@ namespace auto_creamapi
}
Close();
}
}*/
}
}

View File

@ -14,6 +14,7 @@
<PackageReference Include="ini-parser-netstandard" Version="2.5.2" />
<PackageReference Include="MvvmCross" Version="7.1.2" />
<PackageReference Include="MvvmCross.Platforms.Wpf" Version="7.1.2" />
<PackageReference Include="MvvmCross.Plugin.Messenger" Version="7.1.2" />
<PackageReference Include="NinjaNye.SearchExtensions" Version="3.0.1" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />