189 lines
6.4 KiB
C#
189 lines
6.4 KiB
C#
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
using Serilog;
|
|
|
|
namespace Poe2Trade.Core;
|
|
|
|
public class SavedLink
|
|
{
|
|
public string Url { get; set; } = "";
|
|
public string Name { get; set; } = "";
|
|
public bool Active { get; set; } = true;
|
|
public LinkMode Mode { get; set; } = LinkMode.Live;
|
|
public PostAction PostAction { get; set; } = PostAction.Stash;
|
|
public string AddedAt { get; set; } = DateTime.UtcNow.ToString("o");
|
|
}
|
|
|
|
public class SavedSettings
|
|
{
|
|
public bool Paused { get; set; }
|
|
public List<SavedLink> Links { get; set; } = [];
|
|
public string Poe2LogPath { get; set; } = @"C:\Program Files (x86)\Steam\steamapps\common\Path of Exile 2\logs\Client.txt";
|
|
public string Poe2WindowTitle { get; set; } = "Path of Exile 2";
|
|
public string BrowserUserDataDir { get; set; } = "./browser-data";
|
|
public int TravelTimeoutMs { get; set; } = 15000;
|
|
public int StashScanTimeoutMs { get; set; } = 10000;
|
|
public int WaitForMoreItemsMs { get; set; } = 20000;
|
|
public int BetweenTradesDelayMs { get; set; } = 5000;
|
|
public double? WindowX { get; set; }
|
|
public double? WindowY { get; set; }
|
|
public double? WindowWidth { get; set; }
|
|
public double? WindowHeight { get; set; }
|
|
public bool Headless { get; set; } = true;
|
|
public BotMode Mode { get; set; } = BotMode.Trading;
|
|
public MapType MapType { get; set; } = MapType.TrialOfChaos;
|
|
public StashCalibration? StashCalibration { get; set; }
|
|
public StashCalibration? ShopCalibration { get; set; }
|
|
public bool ShowHudDebug { get; set; }
|
|
public KulemakSettings Kulemak { get; set; } = new();
|
|
}
|
|
|
|
public class KulemakSettings
|
|
{
|
|
public bool Enabled { get; set; }
|
|
public string InvitationTabPath { get; set; } = "";
|
|
public string LootTabPath { get; set; } = "";
|
|
public int InvitationCount { get; set; } = 15;
|
|
}
|
|
|
|
public class ConfigStore
|
|
{
|
|
private static readonly JsonSerializerOptions JsonOptions = new()
|
|
{
|
|
WriteIndented = true,
|
|
Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) }
|
|
};
|
|
|
|
private readonly string _filePath;
|
|
private SavedSettings _data;
|
|
|
|
public ConfigStore(string? configPath = null)
|
|
{
|
|
_filePath = configPath ?? Path.GetFullPath("config.json");
|
|
_data = Load();
|
|
}
|
|
|
|
public SavedSettings Settings => _data;
|
|
public IReadOnlyList<SavedLink> Links => _data.Links;
|
|
|
|
public void AddLink(string url, string name = "", LinkMode mode = LinkMode.Live, PostAction? postAction = null)
|
|
{
|
|
url = StripLive(url);
|
|
if (_data.Links.Any(l => l.Url == url)) return;
|
|
_data.Links.Add(new SavedLink
|
|
{
|
|
Url = url,
|
|
Name = name,
|
|
Active = true,
|
|
Mode = mode,
|
|
PostAction = postAction ?? (mode == LinkMode.Scrap ? PostAction.Salvage : PostAction.Stash),
|
|
AddedAt = DateTime.UtcNow.ToString("o")
|
|
});
|
|
Save();
|
|
}
|
|
|
|
public void RemoveLink(string url)
|
|
{
|
|
_data.Links.RemoveAll(l => l.Url == url);
|
|
Save();
|
|
}
|
|
|
|
public void RemoveLinkById(string id)
|
|
{
|
|
_data.Links.RemoveAll(l => l.Url.Split('/').Last() == id);
|
|
Save();
|
|
}
|
|
|
|
public SavedLink? UpdateLinkById(string id, Action<SavedLink> update)
|
|
{
|
|
var link = _data.Links.FirstOrDefault(l => l.Url.Split('/').Last() == id);
|
|
if (link == null) return null;
|
|
update(link);
|
|
Save();
|
|
return link;
|
|
}
|
|
|
|
public void SetPaused(bool paused)
|
|
{
|
|
_data.Paused = paused;
|
|
Save();
|
|
}
|
|
|
|
public void UpdateSettings(Action<SavedSettings> update)
|
|
{
|
|
update(_data);
|
|
Save();
|
|
}
|
|
|
|
public void Save()
|
|
{
|
|
try
|
|
{
|
|
var json = JsonSerializer.Serialize(_data, JsonOptions);
|
|
File.WriteAllText(_filePath, json);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Failed to save config.json to {Path}", _filePath);
|
|
}
|
|
}
|
|
|
|
private SavedSettings Load()
|
|
{
|
|
if (!File.Exists(_filePath))
|
|
{
|
|
Log.Information("No config.json found at {Path}, using defaults", _filePath);
|
|
return new SavedSettings();
|
|
}
|
|
|
|
try
|
|
{
|
|
var raw = File.ReadAllText(_filePath);
|
|
|
|
// Migrate: BossRun was removed from BotMode, now it's MapType.Kulemak
|
|
if (raw.Contains("\"bossRun\"") || raw.Contains("\"BossRun\""))
|
|
{
|
|
const System.Text.RegularExpressions.RegexOptions ic =
|
|
System.Text.RegularExpressions.RegexOptions.IgnoreCase;
|
|
|
|
// Mode enum: bossRun → mapping
|
|
using var doc = JsonDocument.Parse(raw);
|
|
if (doc.RootElement.TryGetProperty("Mode", out var modeProp) &&
|
|
modeProp.GetString()?.Equals("bossRun", StringComparison.OrdinalIgnoreCase) == true)
|
|
{
|
|
raw = System.Text.RegularExpressions.Regex.Replace(
|
|
raw, @"""Mode""\s*:\s*""bossRun""", @"""Mode"": ""mapping""", ic);
|
|
raw = System.Text.RegularExpressions.Regex.Replace(
|
|
raw, @"""MapType""\s*:\s*""[^""]*""", @"""MapType"": ""kulemak""", ic);
|
|
Log.Information("Migrated config: Mode bossRun -> mapping + MapType kulemak");
|
|
}
|
|
|
|
// MapType enum value: bossRun → kulemak
|
|
raw = System.Text.RegularExpressions.Regex.Replace(
|
|
raw, @"""MapType""\s*:\s*""bossRun""", @"""MapType"": ""kulemak""", ic);
|
|
|
|
// Settings property name: BossRun → Kulemak
|
|
raw = raw.Replace("\"BossRun\":", "\"Kulemak\":");
|
|
}
|
|
|
|
var parsed = JsonSerializer.Deserialize<SavedSettings>(raw, JsonOptions);
|
|
if (parsed == null) return new SavedSettings();
|
|
|
|
// Migrate links: strip /live from URLs
|
|
foreach (var link in parsed.Links)
|
|
{
|
|
link.Url = StripLive(link.Url);
|
|
}
|
|
|
|
Log.Information("Loaded config.json from {Path} ({LinkCount} links)", _filePath, parsed.Links.Count);
|
|
return parsed;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Warning(ex, "Failed to read config.json at {Path}, using defaults", _filePath);
|
|
return new SavedSettings();
|
|
}
|
|
}
|
|
|
|
private static string StripLive(string url) => System.Text.RegularExpressions.Regex.Replace(url, @"/live/?$", "");
|
|
}
|