9bb4f85802
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
59 lines
2.3 KiB
C#
59 lines
2.3 KiB
C#
using System.Xml;
|
|
using System.Xml.Linq;
|
|
using CVRManager.Models;
|
|
|
|
namespace CVRManager.Services;
|
|
|
|
public static class AccountService
|
|
{
|
|
const string ProfilePrefix = "cvrm-";
|
|
|
|
public record Found(string Name, string Username, string UserId, string AccessKey);
|
|
|
|
public static string ProfileName(GameAccount a) => ProfilePrefix + a.Id;
|
|
|
|
static string ProfilePath(string gameDir, GameAccount a) => Path.Combine(gameDir, "ChilloutVR_Data", $"autologin-{ProfileName(a)}.profile");
|
|
|
|
public static string WriteProfile(string gameDir, GameAccount a)
|
|
{
|
|
var key = TokenVault.Unprotect(a.AccessKey);
|
|
if (key.Length == 0) throw new InvalidOperationException($"The access key for {a.Name} could not be read; add the account again.");
|
|
var doc = new XElement("LoginProfile",
|
|
new XElement("UserId", a.UserId),
|
|
new XElement("Username", a.Username),
|
|
new XElement("AccessKey", key));
|
|
File.WriteAllText(ProfilePath(gameDir, a), doc.ToString());
|
|
return ProfileName(a);
|
|
}
|
|
|
|
public static IEnumerable<Found> Scan(IEnumerable<string> gameDirs)
|
|
{
|
|
foreach (var dir in gameDirs)
|
|
{
|
|
var data = Path.Combine(dir, "ChilloutVR_Data");
|
|
if (!Directory.Exists(data)) continue;
|
|
foreach (var file in Directory.EnumerateFiles(data, "autologin*.profile"))
|
|
{
|
|
if (Path.GetFileName(file).StartsWith("autologin-" + ProfilePrefix, StringComparison.OrdinalIgnoreCase)) continue;
|
|
if (Read(file) is { } found) yield return found;
|
|
}
|
|
}
|
|
}
|
|
|
|
static Found? Read(string path)
|
|
{
|
|
try
|
|
{
|
|
var root = XDocument.Load(path).Root;
|
|
if (root == null || root.Name != "LoginProfile") return null;
|
|
string Value(string name) => root.Element(name)?.Value.Trim() ?? "";
|
|
var username = Value("Username");
|
|
var key = Value("AccessKey");
|
|
if (username.Length == 0 || key.Length == 0) return null;
|
|
var stem = Path.GetFileNameWithoutExtension(path)["autologin".Length..].TrimStart('_', '-');
|
|
return new Found(stem.Length > 0 ? stem : username, username, Value("UserId"), key);
|
|
}
|
|
catch (Exception e) when (e is IOException or UnauthorizedAccessException or XmlException) { return null; }
|
|
}
|
|
}
|