DisplayMagician/HeliosDisplayManagement/Steam/SteamGame.cs

425 lines
12 KiB
C#
Raw Normal View History

2017-02-26 19:23:31 +00:00
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using HeliosPlus.Resources;
2017-02-26 19:23:31 +00:00
using HtmlAgilityPack;
2017-08-10 14:21:45 +00:00
using Microsoft.Win32;
using Newtonsoft.Json;
2017-02-26 19:23:31 +00:00
namespace HeliosPlus.Steam
2017-02-26 19:23:31 +00:00
{
public class SteamGame
{
private static List<SteamAppIdNamePair> _allGames;
private static bool _allGamesUpdated;
2017-08-10 14:21:45 +00:00
private static readonly object AllGamesLock = new object();
2017-02-26 19:23:31 +00:00
private string _name;
static SteamGame()
{
ServicePointManager.ServerCertificateValidationCallback +=
(send, certificate, chain, sslPolicyErrors) => true;
}
public SteamGame(uint appId)
{
AppId = appId;
}
public uint AppId { get; }
public static string GameIdsPath
2018-10-20 00:27:25 +00:00
{
get => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
Assembly.GetExecutingAssembly().GetName().Name, @"SteamGames.json");
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
public static string IconCache
2018-10-20 00:27:25 +00:00
{
get => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
2017-02-26 19:23:31 +00:00
Assembly.GetExecutingAssembly().GetName().Name, @"SteamIconCache");
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
2017-08-10 14:21:45 +00:00
public bool IsInstalled
2017-02-26 19:23:31 +00:00
{
get
{
try
{
using (
var key = Registry.CurrentUser.OpenSubKey(RegistryApp, RegistryKeyPermissionCheck.ReadSubTree))
{
2017-08-10 14:21:45 +00:00
return (int) (key?.GetValue(@"Installed", 0) ?? 0) > 0;
2017-02-26 19:23:31 +00:00
}
}
catch
{
return false;
}
}
}
2017-08-10 14:21:45 +00:00
public bool IsOwned
2017-02-26 19:23:31 +00:00
{
get
{
try
{
using (
var key = Registry.CurrentUser.OpenSubKey(RegistryApp, RegistryKeyPermissionCheck.ReadSubTree))
{
2017-08-10 14:21:45 +00:00
return key != null;
2017-02-26 19:23:31 +00:00
}
}
catch
{
return false;
}
}
}
2017-08-10 14:21:45 +00:00
public bool IsRunning
2017-02-26 19:23:31 +00:00
{
get
{
try
{
using (
var key = Registry.CurrentUser.OpenSubKey(RegistryApp, RegistryKeyPermissionCheck.ReadSubTree))
{
2017-08-10 14:21:45 +00:00
return (int) (key?.GetValue(@"Running", 0) ?? 0) > 0;
2017-02-26 19:23:31 +00:00
}
}
catch
{
return false;
}
}
}
2017-08-10 14:21:45 +00:00
public bool IsUpdating
2017-02-26 19:23:31 +00:00
{
get
{
try
{
using (
var key = Registry.CurrentUser.OpenSubKey(RegistryApp, RegistryKeyPermissionCheck.ReadSubTree))
{
2017-08-10 14:21:45 +00:00
return (int) (key?.GetValue(@"Updating", 0) ?? 0) > 0;
2017-02-26 19:23:31 +00:00
}
}
catch
{
return false;
}
}
}
2018-10-20 00:27:25 +00:00
public string Name
{
get => _name ?? (_name = GetAppName(AppId));
}
private string RegistryApp
{
get => $@"{RegistryApps}\\{AppId}";
}
private static string RegistryApps
{
get => $@"{RegistrySteam}\\Apps";
}
2017-08-10 14:21:45 +00:00
2018-10-20 00:27:25 +00:00
private static string RegistrySteam
{
get => @"SOFTWARE\\Valve\\Steam";
}
2017-08-10 14:21:45 +00:00
public static string SteamAddress
2017-02-26 19:23:31 +00:00
{
2017-08-10 14:21:45 +00:00
get
2017-02-26 19:23:31 +00:00
{
2017-08-10 14:21:45 +00:00
using (
var key = Registry.CurrentUser.OpenSubKey(RegistrySteam, RegistryKeyPermissionCheck.ReadSubTree))
2017-02-26 19:23:31 +00:00
{
2017-08-10 14:21:45 +00:00
return (string) key?.GetValue(@"SteamExe", string.Empty) ?? string.Empty;
2017-02-26 19:23:31 +00:00
}
2017-08-10 14:21:45 +00:00
}
}
2018-10-20 00:27:25 +00:00
public static bool SteamInstalled
{
get => !string.IsNullOrWhiteSpace(SteamAddress);
}
2017-08-10 14:21:45 +00:00
public static List<SteamAppIdNamePair> GetAllGames()
{
lock (AllGamesLock)
{
if (_allGames == null)
2018-10-20 00:27:25 +00:00
{
2017-08-10 14:21:45 +00:00
_allGames = GetCachedGameIds()?.ToList();
2018-10-20 00:27:25 +00:00
}
2017-08-10 14:21:45 +00:00
}
2018-10-20 00:27:25 +00:00
2017-08-10 14:21:45 +00:00
// Update only once
if (!_allGamesUpdated)
2018-10-20 00:27:25 +00:00
{
2017-08-10 14:21:45 +00:00
if (_allGames?.Count > 0)
2018-10-20 00:27:25 +00:00
{
2017-08-10 14:21:45 +00:00
UpdateGamesFromWeb();
2018-10-20 00:27:25 +00:00
}
2017-08-10 14:21:45 +00:00
else
2018-10-20 00:27:25 +00:00
{
2017-08-10 14:21:45 +00:00
UpdateGamesFromWeb()?.Join();
2018-10-20 00:27:25 +00:00
}
}
2017-08-10 14:21:45 +00:00
return _allGames;
}
public static SteamGame[] GetAllOwnedGames()
{
var list = new List<SteamGame>();
2018-10-20 00:27:25 +00:00
2017-08-10 14:21:45 +00:00
try
{
using (
var subKey = Registry.CurrentUser.OpenSubKey(RegistryApps, RegistryKeyPermissionCheck.ReadSubTree))
2017-02-26 19:23:31 +00:00
{
2017-08-10 14:21:45 +00:00
if (subKey != null)
2018-10-20 00:27:25 +00:00
{
2017-08-10 14:21:45 +00:00
foreach (var keyName in subKey.GetSubKeyNames())
{
uint gameId;
2018-10-20 00:27:25 +00:00
2017-08-10 14:21:45 +00:00
if (uint.TryParse(keyName, out gameId))
2018-10-20 00:27:25 +00:00
{
2017-08-10 14:21:45 +00:00
list.Add(new SteamGame(gameId));
2018-10-20 00:27:25 +00:00
}
2017-08-10 14:21:45 +00:00
}
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
}
2017-08-10 14:21:45 +00:00
}
catch (Exception)
{
// ignored
}
2018-10-20 00:27:25 +00:00
2017-08-10 14:21:45 +00:00
return list.ToArray();
}
public static string GetAppName(uint appId)
{
return GetAllGames()?.FirstOrDefault(g => g.AppId == appId)?.Name;
}
private static void CacheGameIds(IEnumerable<SteamAppIdNamePair> gameIds)
{
try
{
var json = JsonConvert.SerializeObject(gameIds, Formatting.Indented);
2018-10-20 00:27:25 +00:00
if (!string.IsNullOrWhiteSpace(json))
2017-08-10 14:21:45 +00:00
{
var dir = Path.GetDirectoryName(GameIdsPath);
2018-10-20 00:27:25 +00:00
2017-08-10 14:21:45 +00:00
if (dir != null)
2017-02-26 19:23:31 +00:00
{
2017-08-10 14:21:45 +00:00
Directory.CreateDirectory(dir);
File.WriteAllText(GameIdsPath, json, Encoding.Unicode);
2017-02-26 19:23:31 +00:00
}
2017-08-10 14:21:45 +00:00
}
}
catch
{
// ignored
}
}
private static SteamAppIdNamePair[] GetCachedGameIds()
{
try
{
if (File.Exists(GameIdsPath))
{
var json = File.ReadAllText(GameIdsPath, Encoding.Unicode);
2018-10-20 00:27:25 +00:00
if (!string.IsNullOrWhiteSpace(json))
2017-02-26 19:23:31 +00:00
{
return JsonConvert.DeserializeObject<SteamAppIdNamePair[]>(json);
2017-02-26 19:23:31 +00:00
}
}
2017-08-10 14:21:45 +00:00
}
catch
{
// ignored
}
2018-10-20 00:27:25 +00:00
2017-08-10 14:21:45 +00:00
return null;
2017-02-26 19:23:31 +00:00
}
private static Thread UpdateGamesFromWeb()
{
if (_allGamesUpdated)
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
return null;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
_allGamesUpdated = true;
var thread = new Thread(() =>
{
try
{
var newGames = new List<SteamAppIdNamePair>();
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
using (var webClient = new WebClient())
{
webClient.Headers.Add(@"User-Agent",
@"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0");
webClient.Headers.Add(@"Accept", @"text/html,application/xhtml+xml,application/xml;");
var response = webClient.OpenRead(@"https://steamdb.info/api/GetAppList/");
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
if (response != null)
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
using (response)
{
using (var reader = new StreamReader(response))
{
var content = reader.ReadToEnd();
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
if (!string.IsNullOrWhiteSpace(content))
{
dynamic appids = JsonConvert.DeserializeObject(content);
2018-10-20 00:27:25 +00:00
if (appids != null && appids.success == true)
{
2017-02-26 19:23:31 +00:00
foreach (var app in appids.data)
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
try
{
newGames.Add(new SteamAppIdNamePair(uint.Parse(app.Name),
app.Value.Value));
}
catch
{
// ignored
}
2018-10-20 00:27:25 +00:00
}
}
2017-02-26 19:23:31 +00:00
}
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
reader.Close();
}
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
response.Close();
}
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
}
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
if (newGames.Count > 0)
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
lock (AllGamesLock)
{
_allGames = newGames;
CacheGameIds(_allGames);
}
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
}
catch
{
// ignored
}
});
thread.Start();
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
return thread;
}
public override string ToString()
{
var name = Name;
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
if (string.IsNullOrWhiteSpace(name))
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
name = Language.Unknown;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
if (IsRunning)
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
return name + " " + Language.Running;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
if (IsUpdating)
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
return name + " " + Language.Updating;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
if (IsInstalled)
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
return name + " " + Language.Installed;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
if (IsOwned)
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
return name + " " + Language.Not_Installed;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
return name + " " + Language.Not_Owned;
}
2017-08-10 14:21:45 +00:00
public Task<string> GetIcon()
2017-02-26 19:23:31 +00:00
{
2017-08-10 14:21:45 +00:00
return Task.Run(() =>
2017-02-26 19:23:31 +00:00
{
2017-08-10 14:21:45 +00:00
if (!Directory.Exists(IconCache))
2018-10-20 00:27:25 +00:00
{
2017-08-10 14:21:45 +00:00
try
2017-02-26 19:23:31 +00:00
{
2017-08-10 14:21:45 +00:00
Directory.CreateDirectory(IconCache);
}
catch
{
return null;
}
2018-10-20 00:27:25 +00:00
}
2017-08-10 14:21:45 +00:00
var localPath = Path.Combine(IconCache, AppId + ".ico");
2018-10-20 00:27:25 +00:00
2017-08-10 14:21:45 +00:00
if (File.Exists(localPath))
2018-10-20 00:27:25 +00:00
{
2017-08-10 14:21:45 +00:00
return localPath;
2018-10-20 00:27:25 +00:00
}
2017-08-10 14:21:45 +00:00
var iconUrl = new HtmlWeb().Load("https://steamdb.info/app/" + AppId)
.DocumentNode.SelectNodes("//a[@href]")
.Select(node => node.Attributes["href"].Value)
.FirstOrDefault(attribute => attribute.EndsWith(".ico") && attribute.Contains("/" + AppId + "/"));
2018-10-20 00:27:25 +00:00
2017-08-10 14:21:45 +00:00
if (!string.IsNullOrWhiteSpace(iconUrl))
2018-10-20 00:27:25 +00:00
{
2017-08-10 14:21:45 +00:00
try
{
using (var client = new WebClient())
2017-02-26 19:23:31 +00:00
{
2017-08-10 14:21:45 +00:00
client.DownloadFile(iconUrl, localPath);
2017-02-26 19:23:31 +00:00
}
}
2017-08-10 14:21:45 +00:00
catch
2017-02-26 19:23:31 +00:00
{
2017-08-10 14:21:45 +00:00
return null;
2017-02-26 19:23:31 +00:00
}
2018-10-20 00:27:25 +00:00
}
2017-08-10 14:21:45 +00:00
return File.Exists(localPath) ? localPath : null;
});
2017-02-26 19:23:31 +00:00
}
}
}