-
Notifications
You must be signed in to change notification settings - Fork 808
Expand file tree
/
Copy pathWinGetIconsHelper.cs
More file actions
178 lines (138 loc) · 6.77 KB
/
WinGetIconsHelper.cs
File metadata and controls
178 lines (138 loc) · 6.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
using System.Globalization;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Management.Deployment;
using Microsoft.Win32;
using UniGetUI.Core.IconEngine;
using UniGetUI.Core.Logging;
using UniGetUI.PackageEngine.Interfaces;
using UniGetUI.PackageEngine.Managers.WingetManager;
namespace UniGetUI.PackageEngine.Managers.WinGet.ClientHelpers;
internal static class WinGetIconsHelper
{
private static readonly Dictionary<string, string> __msstore_package_manifests = [];
public static string? GetMicrosoftStoreManifest(IPackage package)
{
if (__msstore_package_manifests.TryGetValue(package.Id, out var manifest))
return manifest;
string CountryCode = CultureInfo.CurrentCulture.Name.Split("-")[^1];
string Locale = CultureInfo.CurrentCulture.Name;
string url = $"https://storeedgefd.dsx.mp.microsoft.com/v8.0/sdk/products?market={CountryCode}&locale={Locale}&deviceFamily=Windows.Desktop";
#pragma warning disable SYSLIB0014
var httpRequest = (HttpWebRequest)WebRequest.Create(url);
#pragma warning restore SYSLIB0014
httpRequest.Method = "POST";
httpRequest.ContentType = "application/json";
string data = "{\"productIds\": \"" + package.Id.ToLower() + "\"}";
using (StreamWriter streamWriter = new(httpRequest.GetRequestStream()))
streamWriter.Write(data);
var httpResponse = httpRequest.GetResponse() as HttpWebResponse;
if (httpResponse is null)
{
Logger.Warn($"Null MS Store response for uri={url} and data={data}");
return null;
}
string result;
using (StreamReader streamReader = new(httpResponse.GetResponseStream()))
result = streamReader.ReadToEnd();
Logger.Debug("Microsoft Store API call status code: " + httpResponse.StatusCode);
if (result != "" && httpResponse.StatusCode == HttpStatusCode.OK)
__msstore_package_manifests[package.Id] = result;
return result;
}
public static CacheableIcon? GetMicrosoftStoreIcon(IPackage package)
{
string? ResponseContent = GetMicrosoftStoreManifest(package);
if (ResponseContent is null)
return null;
Match IconArray = Regex.Match(ResponseContent, "(?:\"|')Images(?:\"|'): ?\\[([^\\]]+)\\]");
if (!IconArray.Success)
{
Logger.Warn("Could not parse Images array from Microsoft Store response");
return null;
}
Dictionary<int, string> FoundIcons = [];
foreach (Match ImageEntry in Regex.Matches(IconArray.Groups[1].Value, "{([^}]+)}"))
{
string CurrentImage = ImageEntry.Groups[1].Value;
if (!ImageEntry.Success)
continue;
Match ImagePurpose = Regex.Match(CurrentImage, "(?:\"|')ImagePurpose(?:\"|'): ?(?:\"|')([^'\"]+)(?:\"|')");
if (!ImagePurpose.Success || ImagePurpose.Groups[1].Value != "Tile")
continue;
Match ImageUrl = Regex.Match(CurrentImage, "(?:\"|')Uri(?:\"|'): ?(?:\"|')([^'\"]+)(?:\"|')");
Match ImageSize = Regex.Match(CurrentImage, "(?:\"|')Height(?:\"|'): ?([^,]+)");
if (!ImageUrl.Success || !ImageSize.Success)
continue;
FoundIcons[int.Parse(ImageSize.Groups[1].Value)] = ImageUrl.Groups[1].Value;
}
if (FoundIcons.Count == 0)
{
Logger.Warn($"No Logo image found for package {package.Id} in Microsoft Store response");
return null;
}
Logger.Debug("Choosing icon with size " + FoundIcons.Keys.Max() + " for package " + package.Id + " from Microsoft Store");
string uri = "https:" + FoundIcons[FoundIcons.Keys.Max()];
return new CacheableIcon(new Uri(uri));
}
public static CacheableIcon? GetWinGetPackageIcon(IPackage package)
{
CatalogPackageMetadata? NativeDetails = NativePackageHandler.GetDetails(package);
if (NativeDetails is null) return null;
// Get the actual icon and return it
foreach (Icon? icon in NativeDetails.Icons.ToArray())
if (icon is not null && icon.Url is not null)
// Logger.Debug($"Found WinGet native icon for {package.Id} with URL={icon.Url}");
return new CacheableIcon(new Uri(icon.Url), icon.Sha256);
// Logger.Debug($"Native WinGet icon for Package={package.Id} on catalog={package.Source.Name} was not found :(");
return null;
}
public static CacheableIcon? GetAPPXPackageIcon(IPackage package)
{
string appxId = package.Id.Replace("MSIX\\", "");
string globalPath;
var progsPath = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WindowsApps", appxId);
if (Directory.Exists(progsPath))
{
globalPath = Path.Join(progsPath, "Assets");
if (!Directory.Exists(globalPath)) globalPath = Path.Join(progsPath, "Images");
if (!Directory.Exists(globalPath)) globalPath = progsPath;
}
else
{
progsPath = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "SystemApps", appxId);
globalPath = Path.Join(progsPath, "Assets");
if (!Directory.Exists(globalPath)) globalPath = Path.Join(progsPath, "Images");
if (!Directory.Exists(globalPath)) globalPath = progsPath;
}
if (!Directory.Exists(globalPath))
return null;
string[] logoFiles = Directory.GetFiles(globalPath, "*StoreLogo*.png", SearchOption.TopDirectoryOnly);
if (logoFiles.Length > 0)
return new CacheableIcon(logoFiles[^1]);
logoFiles = Directory.GetFiles(globalPath, "*Splash*.png", SearchOption.TopDirectoryOnly);
if (logoFiles.Length > 0)
return new CacheableIcon(logoFiles[^1]);
logoFiles = Directory.GetFiles(globalPath, "*.png", SearchOption.TopDirectoryOnly);
if (logoFiles.Length > 0)
return new CacheableIcon(logoFiles[^1]);
return null;
}
public static CacheableIcon? GetARPPackageIcon(IPackage package)
{
var bits = package.Id.Split("\\");
if (bits.Length < 4) return null;
string regKey = "";
regKey += bits[1] == "Machine" ? "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER";
regKey += "\\SOFTWARE";
if (bits[2] == "X86")
regKey += "\\WOW6432Node";
regKey += "\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
regKey += bits[3];
string? displayIcon = (string?)Registry.GetValue(regKey, "DisplayIcon", null);
if (!string.IsNullOrEmpty(displayIcon) && File.Exists(displayIcon) && !displayIcon.EndsWith(".exe"))
return new CacheableIcon(displayIcon);
return null;
}
}