using System;
using System.IO;
using System.Text.Json;
namespace codelanguage;
/// Serializable Pager session used for one-click craft:// joins.
public sealed record CraftSavedSession(
string HubUrl,
string Username,
string SessionToken,
DateTimeOffset SavedAtUtc);
///
/// Local, per-user session cache written by the Pager after a successful Hub
/// sign-in. The opaque Hub token lets a newly launched Dream Seeker join a
/// craft:// link without asking the player to type their key again.
///
public static class CraftSessionStore
{
public static string DefaultPath => Path.Combine(
System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData),
"CraftPlusPlus",
"pager-session.json");
public static CraftSavedSession? Load(string? path = null)
{
string file = ResolvePath(path);
try
{
if (!File.Exists(file)) return null;
var session = JsonSerializer.Deserialize(File.ReadAllText(file));
if (session == null || string.IsNullOrWhiteSpace(session.Username) ||
string.IsNullOrWhiteSpace(session.SessionToken))
return null;
return session;
}
catch
{
return null;
}
}
public static void Save(string hubUrl, string username, string sessionToken, string? path = null)
{
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(sessionToken)) return;
string file = ResolvePath(path);
try
{
string? directory = Path.GetDirectoryName(file);
if (!string.IsNullOrEmpty(directory)) Directory.CreateDirectory(directory);
var session = new CraftSavedSession(hubUrl ?? "", username, sessionToken, DateTimeOffset.UtcNow);
string temporary = file + ".tmp";
File.WriteAllText(temporary, JsonSerializer.Serialize(session));
File.Move(temporary, file, overwrite: true);
if (!OperatingSystem.IsWindows())
File.SetUnixFileMode(file, UnixFileMode.UserRead | UnixFileMode.UserWrite);
}
catch
{
// The session cache is best-effort; manual login remains available.
}
}
public static void Clear(string? path = null)
{
string file = ResolvePath(path);
try
{
if (File.Exists(file)) File.Delete(file);
}
catch { }
}
private static string ResolvePath(string? path) =>
string.IsNullOrWhiteSpace(path) ? DefaultPath : path;
}