Skip to content

Commit

Permalink
Checking in before removing the manager project and moving WPF resour…
Browse files Browse the repository at this point in the history
…ces out of Core.
  • Loading branch information
syntax-tm committed May 17, 2024
1 parent 663d70d commit 779da7b
Show file tree
Hide file tree
Showing 33 changed files with 1,315 additions and 689 deletions.
6 changes: 0 additions & 6 deletions src/SAM.ChildProcessDbgSettings

This file was deleted.

84 changes: 84 additions & 0 deletions src/SAM.Console/Options.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommandLine;

namespace SAM.Console;

public enum ListTarget
{
Apps,
Stats,
Achievements,
All
}

public enum ExportTarget
{
AppList,
Stats,
Achievements,
User,
Settings,
All
}

public enum StartTarget
{
SAM,
Steam,
SteamConsole,
SteamApp
}

public enum OutputFormat
{
Json = 0,
Text,
Csv,
Xml,
Yml
}

public abstract class OptionsBase
{
[Option('f', "format", Default = OutputFormat.Json, HelpText = "The format of the results")]
public OutputFormat Format { get; set; }

[Option('o', "outfile", HelpText = "The file to save the results to.")]
public string OutFile { get; set; }

[Option('s', "simple", HelpText = "If set will only show output using plain (non-ANSI) text.")]
public bool SimpleOutput { get; set; }
}

[Verb("manage", true, HelpText = "List available apps, achievements, stats, and more.")]
public class ManageOptions : OptionsBase
{
[Option('a', "app", Default = 0, HelpText = "The app's unique Steam ID.")]
[Value(0, Min = 0, MetaName = "app", HelpText = "The app's unique Steam ID.")]
public uint AppId { get; set; }
}

[Verb("list", false, ["print", "show"], HelpText = "List available apps, achievements, stats, and more.")]
public class ListOptions : OptionsBase
{
[Option('t', "target", Default = ListTarget.All, HelpText = $"The target type to display")]
public ListTarget Target { get; set; }
}

[Verb("export", false, ["save"], HelpText = "Export apps, stats, settings, and more.")]
public class ExportOptions : OptionsBase
{
[Option('t', "target", Default = ListTarget.All, HelpText = $"The information to export")]
public ExportTarget Target { get; set; }
}

[Verb("start", false, ["run", "launch"], HelpText = "Start Steam, Steam Console, installed app, nad more.")]
public class StartOptions : OptionsBase
{
[Option('t', "target", Default = StartTarget.SAM, HelpText = $"The target to start")]
public StartTarget Target { get; set; }
}
47 changes: 47 additions & 0 deletions src/SAM.Console/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// See https://aka.ms/new-console-template for more information

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using CommandLine;
using log4net;
using SAM.Console;

var log = LogManager.GetLogger(nameof(Program));

var helpWriter = new StringWriter();
var parser = new Parser(with =>
{
//ignore case for enum values
with.CaseInsensitiveEnumValues = true;
with.HelpWriter = helpWriter;
});

var options = parser.ParseArguments<ManageOptions, ListOptions, StartOptions>(Environment.GetCommandLineArgs())
.WithParsed<ManageOptions>(HandleManage)
.WithParsed<ListOptions>(opts => opts.ToString())
.WithParsed<StartOptions>(opts => opts.ToString())
.WithNotParsed(errs => DisplayHelp(errs, helpWriter));

Console.WriteLine("Hello, World!");

// ReSharper disable once InconsistentNaming
static void DisplayHelp(IEnumerable<Error> err, TextWriter helpWriter)
{
var errors = err.ToList();

if (errors.IsVersion() || errors.IsHelp())
{
Console.WriteLine(helpWriter.ToString());
}
else
{
Console.Error.WriteLine(helpWriter.ToString());
}
}

static void HandleManage(ManageOptions options)
{

}
15 changes: 15 additions & 0 deletions src/SAM.Console/SAM.Console.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.9.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\SAM.Core\SAM.Core.csproj" />
</ItemGroup>

</Project>
135 changes: 69 additions & 66 deletions src/SAM.Core/API/Steamworks/SAMLibraryHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,103 +2,106 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Xml.XPath;
using System.Xml;
using log4net;
using SAM.Core.Storage;

namespace SAM.Core
namespace SAM.Core;

public static class SAMLibraryHelper
{
public static class SAMLibraryHelper
{
// TODO: Make this a configurable setting
private const string SAM_GAME_LIST_URL = @"http://gib.me/sam/games.xml";
// TODO: Make this a configurable setting
private const string SAM_GAME_LIST_URL = @"http://gib.me/sam/games.xml";

private static readonly ILog log = LogManager.GetLogger(nameof(SAMLibraryHelper));
private static readonly ILog log = LogManager.GetLogger(nameof(SAMLibraryHelper));

// TODO: Store this somewhere outside the application so that it can be actively maintained separately
private static readonly uint[] _ignoredApps =
{
13260 // Unreal Development Kit
};
private static ConcurrentDictionary<uint, SupportedApp> _gameList;
private static ConcurrentDictionary<uint, SupportedApp> _gameList;

private static readonly HttpClient client = new ();
private static readonly HttpClient client = new ();

public static IDictionary<uint, SupportedApp> Apps
public static IDictionary<uint, SupportedApp> Apps
{
get
{
get
{
if (_gameList != null) return _gameList;
if (_gameList != null) return _gameList;

_gameList = new (GetSupportedGames());
_gameList = new (GetSupportedGames());

return _gameList;
}
return _gameList;
}
}

public static IDictionary<uint, SupportedApp> GetSupportedGames()
{
if (_gameList != null) return _gameList;
public static bool TryGetApp(uint id, out SupportedApp app)
{
return Apps.TryGetValue(id, out app);
}

try
{
_gameList = [ ];
// TODO: give this a different name so that it's distinct from TryGetApp
public static SupportedApp GetApp(uint id)
{
// this method is used when SAM is managing an app so that it loads only the
// requested app. in every other situation, all Apps are loaded into the list
var apps = GetSupportedGames(id);

if (apps.TryGetValue(id, out var app)) return app;

using var request = new HttpRequestMessage(HttpMethod.Get, SAM_GAME_LIST_URL);
var response = client.Send(request);
var responseStream = response.Content.ReadAsStream();
var message = $"App '{id}' is not currently supported.";
throw new SAMException(message);
}

var document = new XPathDocument(responseStream);
var navigator = document.CreateNavigator();
private static IDictionary<uint, SupportedApp> GetSupportedGames(uint? appId = null)
{
if (_gameList != null) return _gameList;

Debug.Assert(navigator is not null, $"The {nameof(XPathNavigator)} cannot be null.");
try
{
_gameList = [ ];

var nodes = navigator.Select("/games/game");
var cacheKey = CacheKeys.Games;

while (nodes.MoveNext())
{
var gameId = (uint) nodes.Current!.ValueAsLong;
if (!CacheManager.TryGetTextFile(cacheKey, out var gamesXml))
{
var response = AsyncHelper.RunSync(() => client.GetAsync(SAM_GAME_LIST_URL));
gamesXml = AsyncHelper.RunSync(() => response.Content.ReadAsStringAsync());

if (_ignoredApps.Contains(gameId))
{
log.Debug($"Skipping app id '{gameId}'.");
continue;
}
CacheManager.CacheText(cacheKey, gamesXml);
}

var type = nodes.Current.GetAttribute("type", string.Empty);
if (string.IsNullOrEmpty(type))
{
type = "normal";
}
var doc = new XmlDocument();
doc.LoadXml(gamesXml);

_gameList[gameId] = new (gameId, type);
}
var query = appId == null
? "/games/game"
: $"/games/game[text()=\"{appId}\"]";

return _gameList;
}
catch (Exception e)
var nodes = doc.SelectNodes(query);

foreach (XmlNode node in nodes)
{
var message = $"An error occurred getting the list of supported apps. {e.Message}";
Debug.Assert(node != null, $"{nameof(node)} is null");

log.Error(message, e);
var id = node.FirstChild?.Value ?? throw new SAMException($"Invalid configuration data. Missing {nameof(XmlNode)} {nameof(XmlNode.Value)} for app.");
var gameId = uint.Parse(id);

var type = node.Attributes?["type"]?.Value;
if (string.IsNullOrEmpty(type))
{
type = "normal";
}

throw new SAMException(message, e);
_gameList[gameId] = new (gameId, type);
}
}

public static bool TryGetApp(uint id, out SupportedApp app)
{
return Apps.TryGetValue(id, out app);
return _gameList;
}

// TODO: Add a way to check and see if an app is supported instead of just trying it
public static SupportedApp GetApp(uint id)
catch (Exception e)
{
if (Apps.TryGetValue(id, out var app)) return app;
var message = $"An error occurred getting the list of supported apps. {e.Message}";

log.Error(message, e);

var message = $"App '{id}' is not currently supported.";
throw new SAMException(message);
throw new SAMException(message, e);
}
}
}
2 changes: 1 addition & 1 deletion src/SAM.Core/API/Steamworks/SteamworksManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static class SteamworksManager
// ReSharper disable once InconsistentNaming
private static readonly HttpClient _client = new ();
// ReSharper disable once InconsistentNaming
private static readonly ConcurrentQueue<SteamApp> _refreshQueue = new ();
private static readonly ConcurrentQueue<SteamApp> _refreshQueue = [ ];
private static BackgroundWorker _refreshWorker;

public static Dictionary<uint, string> GetAppList()
Expand Down
2 changes: 1 addition & 1 deletion src/SAM.Core/Models/SteamApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public partial class SteamApp : ViewModelBase
[GenerateProperty] private bool _isMenuOpen;
public bool StoreInfoLoaded => StoreInfo != null;

public SteamApp(uint id, GameInfoType type)
public SteamApp(uint id, GameInfoType type = GameInfoType.Normal)
{
Id = id;
GameInfoType = type;
Expand Down
2 changes: 1 addition & 1 deletion src/SAM.Core/Models/SteamLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public partial class SteamLibrary : BindableBase

public SteamLibrary()
{
_supportedGames = SAMLibraryHelper.GetSupportedGames();
_supportedGames = SAMLibraryHelper.Apps;

SupportedGamesCount = _supportedGames.Count;

Expand Down
Loading

0 comments on commit 779da7b

Please sign in to comment.