Skip to content

Commit e610e80

Browse files
committed
Update packages and refactor main application components
- Updated package versions in `Directory.Packages.props` for Microsoft.Extensions and `PuppeteerSharp`. - Modified `btn_Cancel` style in `MainForm.Designer.cs`. - Replaced `IEventAggregator` subscriptions with new event handlers in `MainForm.cs`. - Added methods in `MainForm.cs` for updating UI with page, link, and queue counts. - Improved error handling in `MainForm.cs` by removing `_aggregator` usage. - Updated `ExtractTargetLinksAsync` in `BlogScraper.cs` to accept a `CancellationToken`. - Refactored `DataLayer.cs` for better error handling and added asynchronous methods. - Enhanced `UrlDownloader.cs` with new events for download completion and failure. - Improved `WebAutomationService.cs` with methods for text extraction and browser health checks. - Added configuration files for Data API Builder setup. - Refactored `Program.cs` for better dependency injection and logging setup.
1 parent ac6f2a4 commit e610e80

18 files changed

+920
-608
lines changed

.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dab-connection-string=Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\kcrow\Documents\Data\Solutions\MediaRecycler\MediaRecycler\Model\Database1.mdf;Integrated Security=True;Connect Timeout=30

Directory.Packages.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@
1515
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="10.0.0-preview.5.25277.114" />
1616
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0-preview.5.25277.114" />
1717
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0-preview.5.25277.114" />
18-
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.6" />
18+
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.0-preview.5.25277.114" />
1919
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.0-preview.5.25277.114" />
2020
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0-preview.5.25277.114" />
2121
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="10.0.0-preview.5.25277.114" />
2222
<PackageVersion Include="Microsoft.Extensions.Logging.Debug" Version="10.0.0-preview.5.25277.114" />
2323
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.0-preview.5.25277.114" />
2424
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.0-preview.5.25277.114" />
2525
<PackageVersion Include="Polly" Version="8.6.1" />
26-
<PackageVersion Include="PuppeteerSharp" Version="20.1.3" />
26+
<PackageVersion Include="PuppeteerSharp" Version="20.2.0" />
2727
<PackageVersion Include="puppeteersharp.dom" Version="5.0.43" />
2828
<PackageVersion Include="System.Text.Json" Version="10.0.0-preview.5.25277.114" />
2929
</ItemGroup>

Forms/MainForm.Designer.cs

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Forms/MainForm.cs

Lines changed: 50 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ namespace MediaRecycler;
2121
public partial class MainForm : Form
2222
{
2323

24-
private readonly IEventAggregator _aggregator = new EventAggregator();
2524

2625
//private UrlDownloader? _downloadManager;
2726
//private readonly IScraper? _scraper;
@@ -41,22 +40,64 @@ public MainForm(IBlogScraper blogScraper)
4140
_blogScraper = blogScraper;
4241

4342
// subscribe to the aggregator for the events we are interested in and assign the handlers
44-
_aggregator.Subscribe<StatusMessage>(OnStatusMessageReceived);
45-
_aggregator.Subscribe<PageNumberMessage>(OnPageCountUpdates);
46-
_aggregator.Subscribe<QueueCountMessage>(OnQueueCountUpdates);
47-
_aggregator.Subscribe<StatusBarMessage>(OnStatusBarMessageReceivced);
43+
44+
Log.UIUpdateQueue += (i) => UpdateQueueDelegate(i);
45+
Log.UIUpdateLinkCount += (i) => UpdateLinkCount(i);
46+
Log.UIUpdatePageCount += (i) => UpdatePageCount(i);
47+
48+
49+
50+
}
4851

4952

5053

5154

5255

56+
57+
private void UpdatePageCount(int i)
58+
{
59+
if (InvokeRequired)
60+
{
61+
Invoke(new Action<int>(UpdatePageCount), i);
62+
return;
63+
}
64+
65+
tb_pages.Text = i.ToString();
5366
}
5467

5568

5669

5770

5871

5972

73+
private void UpdateLinkCount(int i)
74+
{
75+
if (InvokeRequired)
76+
{
77+
Invoke(new Action<int>(UpdateLinkCount), i);
78+
return;
79+
}
80+
81+
tb_videos.Text = i.ToString();
82+
}
83+
84+
85+
86+
87+
88+
89+
private void UpdateQueueDelegate(int i)
90+
{
91+
if (InvokeRequired)
92+
{
93+
Invoke(new Action<int>(UpdateQueueDelegate),i);
94+
}
95+
96+
tb_dlque.Text = i.ToString();
97+
}
98+
99+
100+
60101
#pragma warning disable IDE0032
61102
/// <summary>
62103
/// Text box used for logging output in the main viewer.
@@ -118,7 +159,6 @@ private async void btn_download_Click(object sender, EventArgs e)
118159
{
119160

120161
Log.LogError(ex, "An unhandled error occured. Attempting to save progress before aborting...");
121-
_aggregator.Publish(new StatusBarMessage("Downloading of videos ended in failure."));
122162

123163

124164

@@ -127,7 +167,6 @@ private async void btn_download_Click(object sender, EventArgs e)
127167
{
128168

129169

130-
_aggregator.Publish(new StatusBarMessage("Downloading of videos complete."));
131170
Log.LogInformation("Video Queue finished.");
132171
}
133172

@@ -145,7 +184,7 @@ private async void btn_Process_Click(object sender, EventArgs e)
145184

146185
try
147186
{
148-
await _blogScraper.ExtractTargetLinksAsync();
187+
await _blogScraper.ExtractTargetLinksAsync(cts.Token);
149188
}
150189
catch (Exception)
151190
{
@@ -358,20 +397,11 @@ private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
358397
// Ensure resources are stopped and disposed of properly
359398
try
360399
{
361-
/*
362-
if (_scraper != null)
363-
{
364-
await _scraper.CancelAsync();
365-
await _scraper.DisposeAsync();
366-
}
400+
401+
_blogScraper?.CancelAsync();
402+
_blogScraper?.DisposeAsync();
367403

368404

369-
if (_downloadManager != null)
370-
{
371-
await _downloadManager.StopAllTasksAsync();
372-
await _downloadManager.DisposeAsync();
373-
}
374-
*/
375405
}
376406
catch (Exception ex)
377407
{
@@ -380,8 +410,6 @@ private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
380410
finally
381411
{
382412
Log.LogInformation("MainForm is closing. PuppeteerManager disposed.");
383-
_aggregator.Unsubscribe<StatusMessage>(OnStatusMessageReceived);
384-
_aggregator.Unsubscribe<PageNumberMessage>(OnPageCountUpdates);
385413
}
386414
}
387415

@@ -400,44 +428,6 @@ private void MainForm_Load(object sender, EventArgs e)
400428

401429

402430

403-
/// <summary>
404-
/// A registered handler for <see cref="EventAggregator" /> Handles updates to the page count by processing the
405-
/// provided <see cref="PageNumberMessage" />.
406-
/// </summary>
407-
/// <param name="pageNumberMessage">
408-
/// The message containing the updated page number information.
409-
/// </param>
410-
private void OnPageCountUpdates(PageNumberMessage pageNumberMessage)
411-
{
412-
if (InvokeRequired)
413-
{
414-
_ = BeginInvoke(() => OnPageCountUpdates(pageNumberMessage));
415-
return;
416-
}
417-
418-
tb_pages.Text = pageNumberMessage.PageNumber.ToString();
419-
}
420-
421-
422-
423-
424-
425-
426-
private void OnQueueCountUpdates(QueueCountMessage obj)
427-
{
428-
if (InvokeRequired)
429-
{
430-
_ = BeginInvoke(() => OnQueueCountUpdates(obj));
431-
return;
432-
433-
434-
}
435-
436-
tb_dlque.Text = obj.QueueCount.ToString();
437-
}
438-
439-
440-
441431

442432

443433

Logging/FormattedLogValues.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,60 @@
1616
namespace MediaRecycler.Logging;
1717

1818

19+
/// <summary>
20+
/// Represents a formatted log message and its named values for structured logging.
21+
/// <para>
22+
/// <b>Purpose:</b> This struct is used to format log messages with named placeholders (e.g., "User {UserId} logged
23+
/// in")
24+
/// and expose both the formatted string and its named values as key-value pairs. This enables efficient structured
25+
/// logging,
26+
/// where log consumers can access both the rendered message and its parameters.
27+
/// </para>
28+
/// <para>
29+
/// <b>How it works:</b>
30+
/// <list type="bullet">
31+
/// <item>
32+
/// <description>
33+
/// When constructed, it takes a format string and an array of values. If the format string and values
34+
/// are valid,
35+
/// it uses a cached <see cref="LogValuesFormatter" /> to parse and format the message. The cache is
36+
/// limited to <see cref="MaxCachedFormatters" /> entries for efficiency.
37+
/// </description>
38+
/// </item>
39+
/// <item>
40+
/// <description>
41+
/// The struct implements <see cref="IReadOnlyList{T}" /> of
42+
/// <see cref="KeyValuePair{String, Object}" />, exposing each named value in the format string,
43+
/// plus a final entry with the key "{OriginalFormat}" containing the original format string.
44+
/// </description>
45+
/// </item>
46+
/// <item>
47+
/// <description>
48+
/// The <see cref="ToString" /> method returns the formatted message, caching the result for repeated
49+
/// calls.
50+
/// </description>
51+
/// </item>
52+
/// <item>
53+
/// <description>
54+
/// If no formatter is available (e.g., null or empty format/values), it simply returns the original
55+
/// message or a "[null]" placeholder.
56+
/// </description>
57+
/// </item>
58+
/// </list>
59+
/// </para>
60+
/// <para>
61+
/// <b>Example:</b>
62+
/// <code>
63+
/// var logValues = new FormattedLogValues("User {UserId} logged in at {Time}", 42, DateTime.Now);
64+
/// string message = logValues.ToString(); // "User 42 logged in at 7/2/2025 10:00:00 AM"
65+
/// foreach (var pair in logValues)
66+
/// {
67+
/// // pair.Key: "UserId", "Time", "{OriginalFormat}"
68+
/// // pair.Value: 42, DateTime.Now, "User {UserId} logged in at {Time}"
69+
/// }
70+
/// </code>
71+
/// </para>
72+
/// </summary>
1973
internal struct FormattedLogValues : IReadOnlyList<KeyValuePair<string, object?>>
2074
{
2175

Logging/Log.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,58 @@ private static void WriteLog(string formattedMessage)
289289

290290

291291

292+
public static void UpdateQueue(int value)
293+
{
294+
lock (_lock)
295+
{
296+
UIUpdateQueue?.Invoke(value);
297+
}
298+
}
299+
300+
301+
302+
303+
304+
305+
public static void UpdatePageCount(int value)
306+
{
307+
lock (_lock)
308+
{
309+
UIUpdatePageCount?.Invoke(value);
310+
}
311+
}
312+
313+
public static void UpdateLinkCount(int value)
314+
{
315+
lock (_lock)
316+
{
317+
UIUpdateLinkCount?.Invoke(value);
318+
}
319+
}
320+
321+
/// <summary>
322+
///
323+
/// </summary>
292324
public static Action<string>? WriteMessage;
293325

326+
/// <summary>
327+
/// Action for queue textbox UI updates
328+
/// </summary>
329+
public static Action<int>? UIUpdateQueue;
330+
331+
332+
/// <summary>
333+
/// Action for page number textbox update
334+
/// </summary>
335+
public static Action<int>? UIUpdatePageCount;
336+
337+
338+
/// <summary>
339+
/// Represents an action that updates the UI with the current link count.
340+
/// </summary>
341+
/// <remarks>This delegate can be assigned to a method that takes an integer parameter, representing the
342+
/// number of links, and performs a UI update based on that value. If not assigned, no action will be performed when
343+
/// invoked.</remarks>
344+
public static Action<int>? UIUpdateLinkCount;
345+
294346
}

MediaRecycler.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<UserSecretsId>fd576e9f-aea8-4045-a046-1df6c55b5f5c</UserSecretsId>
2020
<NuGetAuditMode>direct</NuGetAuditMode>
2121
<NuGetAuditLevel>critical</NuGetAuditLevel>
22+
<SupportedOSPlatformVersion>8.0</SupportedOSPlatformVersion>
2223
</PropertyGroup>
2324
<ItemGroup>
2425
<Compile Remove="Migrations\**" />

0 commit comments

Comments
 (0)