-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAppConfig.cs
More file actions
116 lines (100 loc) · 4.78 KB
/
Copy pathAppConfig.cs
File metadata and controls
116 lines (100 loc) · 4.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
using System;
using System.IO;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
namespace WebToolsDataMonitor
{
// Remembered Form1 UI state - saved automatically whenever a control changes, restored at startup.
public class UiStateConfig
{
public bool ParallelTools { get; set; } = true;
public bool ParallelPages { get; set; } = false;
public int IntervalSeconds { get; set; } = 60;
}
// Remembered Form2 sound/speech alert settings - saved automatically whenever a control changes,
// restored at startup. See Form2.ProcessAlerts.
public class AlertsConfig
{
// "Off" | "Info" | "Warning" | "Average" | "Disaster" - minimum severity that triggers a sound/
// speech alert. Default matches "warning, average, or disaster should play a sound" - Info is
// opt-in, not the default, since it fires on every non-normal row.
public string Threshold { get; set; } = "Warning";
// Whether to also speak "<device>, <metric>" via Windows' built-in TTS when an alert fires.
public bool SpeakDeviceAndMetric { get; set; } = true;
}
public class AppConfigData
{
// Supported levels in order of severity: DEBUG, INFO, WARNING, ERROR, CRITICAL
public string MinLogLevel { get; set; } = "INFO";
public bool LogToFile { get; set; } = true;
public string LogFilePath { get; set; } = "scraper_execution.log";
// Global default applied to any tool that doesn't set its own disableCache in tools/*.yaml.
// true = always clear that tool's CacheData/<ToolName> folder after every run (forces a fresh
// login next time - needed for sites whose persistent session cookie otherwise survives
// across runs and gets misread as a login failure).
// false = never clear it (preserves the WebView2 profile - browser cache, not just cookies -
// across runs; needed for slow/weak devices whose SPA can't fully cold-bootstrap within
// the login retry window without a warm HTTP cache).
public bool DefaultDisableCache { get; set; } = true;
public UiStateConfig Ui { get; set; } = new UiStateConfig();
public AlertsConfig Alerts { get; set; } = new AlertsConfig();
}
// Single global YAML-backed config file (app_config.yaml) holding logger settings, engine-wide
// defaults, and remembered Form1 UI state. Explicitly initialized once at startup in Program.cs,
// before anything else (including Logger) touches configuration, so there's one canonical load point
// instead of each subsystem independently parsing its own slice of the file.
public class AppConfig
{
private const string ConfigFileName = "app_config.yaml";
private static readonly Lazy<AppConfig> _instance = new Lazy<AppConfig>(() => new AppConfig());
public static AppConfig Instance => _instance.Value;
private readonly object _lockObj = new object();
private readonly string _configPath;
public AppConfigData Data { get; private set; }
private AppConfig()
{
_configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigFileName);
Data = Load();
}
private AppConfigData Load()
{
if (!File.Exists(_configPath))
{
return new AppConfigData();
}
try
{
string yamlContent = File.ReadAllText(_configPath);
var deserializer = new DeserializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.IgnoreUnmatchedProperties()
.Build();
return deserializer.Deserialize<AppConfigData>(yamlContent) ?? new AppConfigData();
}
catch
{
return new AppConfigData();
}
}
// Persists the current in-memory Data back to app_config.yaml - used to remember Form1's UI state
// across restarts. Best-effort: a write failure (locked/read-only file) is swallowed rather than
// crashing the UI, matching this project's existing config/log write conventions.
public void Save()
{
lock (_lockObj)
{
try
{
var serializer = new SerializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.Build();
File.WriteAllText(_configPath, serializer.Serialize(Data));
}
catch
{
// Best-effort - don't let a config write failure break the UI
}
}
}
}
}