Skip to content

Commit

Permalink
Added downloading of packages.
Browse files Browse the repository at this point in the history
  • Loading branch information
BartoszCichecki committed Jun 29, 2022
1 parent e28d03f commit d998d3c
Show file tree
Hide file tree
Showing 14 changed files with 532 additions and 41 deletions.
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,6 @@ PublishScripts/
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
Expand Down
10 changes: 10 additions & 0 deletions LenovoLegionToolkit.Lib/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ public enum HybridModeState
Off,
}

public enum KnownFolder
{
Contacts,
Downloads,
Favorites,
Links,
SavedGames,
SavedSearches
}

public enum OverDriveState
{
Off,
Expand Down
26 changes: 26 additions & 0 deletions LenovoLegionToolkit.Lib/Structs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,32 @@ public MachineInformation(string vendor, string model)
}
}

public struct Package
{
public string Description { get; }
public string Version { get; }
public string Category { get; }
public string FileName { get; }
public int FileSize { get; }
public string CRC { get; }
public DateTime ReleaseDate { get; }
public string? ReadMe { get; }
public string FileLocation { get; }

public Package(string description, string version, string category, string fileName, int fileSize, string crc, DateTime releaseDate, string? readMe, string fileLocation)
{
Description = description;
Version = version;
Category = category;
FileName = fileName;
FileSize = fileSize;
CRC = crc;
ReleaseDate = releaseDate;
ReadMe = readMe;
FileLocation = fileLocation;
}
}

public struct PowerPlan
{
public string InstanceID { get; }
Expand Down
20 changes: 20 additions & 0 deletions LenovoLegionToolkit.Lib/System/KnownFolders.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;

namespace LenovoLegionToolkit.Lib.System
{
public static class KnownFolders
{
private static readonly Dictionary<KnownFolder, Guid> _guids = new()
{
[KnownFolder.Contacts] = new("56784854-C6CB-462B-8169-88E350ACB882"),
[KnownFolder.Downloads] = new("374DE290-123F-4565-9164-39C4925E467B"),
[KnownFolder.Favorites] = new("1777F761-68AD-4D8A-87BD-30B759FA33DD"),
[KnownFolder.Links] = new("BFB9D5E0-C6A9-404C-B2B2-AE6DB6AF4968"),
[KnownFolder.SavedGames] = new("4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4"),
[KnownFolder.SavedSearches] = new("7D1D3A04-DEBB-4115-95CF-2F29DA2920DA")
};

public static string GetPath(KnownFolder knownFolder) => Native.SHGetKnownFolderPath(_guids[knownFolder], 0);
}
}
3 changes: 3 additions & 0 deletions LenovoLegionToolkit.Lib/System/Native.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ internal static class Native

public const int ERROR_NO_MORE_ITEMS = 259;

[DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
public static extern string SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, nint hToken = 0);

[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetupDiGetClassDevs(
ref Guid guid,
Expand Down
49 changes: 19 additions & 30 deletions LenovoLegionToolkit.Lib/Utils/PackageDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,13 @@
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using LenovoLegionToolkit.Lib.Extensions;

namespace LenovoLegionToolkit.Lib.Utils
{
public struct Package
{
public string Description { get; }
public string Category { get; }
public string FileName { get; }
public int FileSize { get; }
public string CRC { get; }
public DateTime ReleaseDate { get; }
public string? ReadMe { get; }

public Package(string description, string category, string fileName, int fileSize, string crc, DateTime releaseDate, string? readMe)
{
Description = description;
Category = category;
FileName = fileName;
FileSize = fileSize;
CRC = crc;
ReleaseDate = releaseDate;
ReadMe = readMe;
}
}

public class PackageDownloader
{
private struct PackageDefinition
Expand All @@ -49,19 +26,26 @@ public PackageDefinition(string location, string category)
}

private readonly string _catalogBaseUrl = "https://download.lenovo.com/catalog/";
private readonly string _packagesBaseUrl = "https://download.lenovo.com/pccbbs/mobiles";

public async Task<List<Package>> GetPackagesAsync(string machineType, string os, CancellationToken token)
public async Task<List<Package>> GetPackagesAsync(string machineType, string os, IProgress<float>? progress = null, CancellationToken token = default)
{
using var httpClient = new HttpClient();

progress?.Report(0);

var packageDefinitions = await GetPackageDefinitionsAsync(httpClient, $"{_catalogBaseUrl}/{machineType}_{os}.xml", token).ConfigureAwait(false);

var count = 0;
var totalCount = packageDefinitions.Count;

var packages = new List<Package>();
foreach (var packageDefinition in packageDefinitions)
{
var package = await GetPackage(httpClient, packageDefinition, token).ConfigureAwait(false);
packages.Add(package);

count++;
progress?.Report((count * 100) / totalCount);
}

return packages;
Expand All @@ -74,13 +58,13 @@ public async Task<string> DownloadPackageFileAsync(Package package, string locat
var tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());

using (var fileStream = File.OpenWrite(tempPath))
await httpClient.DownloadAsync($"{_packagesBaseUrl}/{package.FileName}", fileStream, progress, token).ConfigureAwait(false);
await httpClient.DownloadAsync(package.FileLocation, fileStream, progress, token).ConfigureAwait(false);

var fileInfo = new FileInfo(tempPath);
if (fileInfo.Length != package.FileSize)
throw new InvalidDataException("File size mismatch.");

var sha256 = await httpClient.GetStringAsync($"{_packagesBaseUrl}/{package.FileName}.sha256", token).ConfigureAwait(false);
var sha256 = await httpClient.GetStringAsync($"{package.FileLocation}.sha256", token).ConfigureAwait(false);

using (var fileStream = File.OpenRead(tempPath))
{
Expand Down Expand Up @@ -132,21 +116,26 @@ private async Task<List<PackageDefinition>> GetPackageDefinitionsAsync(HttpClien

private async Task<Package> GetPackage(HttpClient httpClient, PackageDefinition packageDefinition, CancellationToken token)
{
var packageString = await httpClient.GetStringAsync(packageDefinition.Location, token).ConfigureAwait(false);
var location = packageDefinition.Location;
var baseLocation = location.Remove(location.LastIndexOf("/"));

var packageString = await httpClient.GetStringAsync(location, token).ConfigureAwait(false);

var document = new XmlDocument();
document.LoadXml(packageString);

var description = document.SelectSingleNode("/Package/Title/Desc")!.InnerText;
var version = document.SelectSingleNode("/Package/@version")!.InnerText;
var fileName = document.SelectSingleNode("/Package/Files/Installer/File/Name")!.InnerText;
var fileSize = int.Parse(document.SelectSingleNode("/Package/Files/Installer/File/Size")!.InnerText);
var crc = document.SelectSingleNode("/Package/Files/Installer/File/CRC")!.InnerText;
var releaseDateString = document.SelectSingleNode("/Package/ReleaseDate")!.InnerText;
var releaseDate = DateTime.Parse(releaseDateString);
var readMeName = document.SelectSingleNode("/Package/Files/Readme/File/Name")?.InnerText;
var readMe = await GetReadmeAsync(httpClient, $"{_packagesBaseUrl}/{readMeName}", token).ConfigureAwait(false);
var readMe = await GetReadmeAsync(httpClient, $"{baseLocation}/{readMeName}", token).ConfigureAwait(false);
var fileLocation = $"{baseLocation}/{fileName}";

return new(description, packageDefinition.Category, fileName, fileSize, crc, releaseDate, readMe);
return new(description, version, packageDefinition.Category, fileName, fileSize, crc, releaseDate, readMe, fileLocation);
}

private async Task<string?> GetReadmeAsync(HttpClient httpClient, string location, CancellationToken token)
Expand Down
6 changes: 0 additions & 6 deletions LenovoLegionToolkit.WPF/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ public partial class App : Application

private async void Application_Startup(object sender, StartupEventArgs e)
{
var result = await new PackageDownloader().GetPackagesAsync("82JQ", "win11", default);

var result2 = await new PackageDownloader().DownloadPackageFileAsync(result.First(), "C:\\");

Debugger.Break();

if (IsTraceEnabled(e.Args))
Log.Instance.IsTraceEnabled = true;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
Expand Down
27 changes: 25 additions & 2 deletions LenovoLegionToolkit.WPF/Controls/LoadableControl.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Wpf.Ui.Controls;

namespace LenovoLegionToolkit.WPF.Controls
Expand All @@ -13,8 +14,8 @@ public class LoadableControl : UserControl
IsIndeterminate = true,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Center,
Width = 32,
Height = 32,
Width = 48,
Height = 48,
};

private bool _isLoading = true;
Expand All @@ -29,6 +30,18 @@ public bool IsLoading
}
}

public bool IsIndeterminate
{
get => _progressRing.IsIndeterminate;
set => _progressRing.IsIndeterminate = value;
}

public double Progress
{
get => _progressRing.Progress;
set => _progressRing.Progress = value;
}

public double IndicatorWidth
{
get => _progressRing.Width;
Expand Down Expand Up @@ -61,6 +74,16 @@ protected override void OnInitialized(EventArgs e)

_contentPresenter.Content = Content;

_progressRing.RenderTransformOrigin = new(0.5, 0.5);
_progressRing.RenderTransform = new TransformGroup
{
Children =
{
new RotateTransform(-90),
new ScaleTransform(-1, 1),
}
};

var grid = new Grid();
grid.Children.Add(_contentPresenter);
grid.Children.Add(_progressRing);
Expand Down
Loading

0 comments on commit d998d3c

Please sign in to comment.