From d641ebe07ef464feda7256165faa7c40c1c683c0 Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:39:34 +0900 Subject: [PATCH 01/10] Update CCFSharpUtils and use new pluralization funcs --- src/CCVTAC.Main/CCVTAC.Main.fsproj | 2 +- src/CCVTAC.Main/Orchestrator.fs | 6 +++--- src/CCVTAC.Main/ResultTracker.fs | 6 +++--- src/CCVTAC.Main/Settings/Settings.fs | 9 +++++---- src/CCVTAC.Tests/CCVTAC.Tests.fsproj | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/CCVTAC.Main/CCVTAC.Main.fsproj b/src/CCVTAC.Main/CCVTAC.Main.fsproj index ef0212a..4a588d2 100644 --- a/src/CCVTAC.Main/CCVTAC.Main.fsproj +++ b/src/CCVTAC.Main/CCVTAC.Main.fsproj @@ -40,7 +40,7 @@ - + diff --git a/src/CCVTAC.Main/Orchestrator.fs b/src/CCVTAC.Main/Orchestrator.fs index f0969f9..60e4e00 100644 --- a/src/CCVTAC.Main/Orchestrator.fs +++ b/src/CCVTAC.Main/Orchestrator.fs @@ -29,8 +29,8 @@ module Orchestrator = : unit = if List.hasMultiple categorizedInputs then - let urlSummary = String.pluralizeWithCount "URL" "URLs" counts[InputCategory.Url] - let cmdSummary = String.pluralizeWithCount "command" "commands" counts[InputCategory.Command] + let urlSummary = String.pluralizeSWithCount "URL" counts[InputCategory.Url] + let cmdSummary = String.pluralizeSWithCount "command" counts[InputCategory.Command] printer.Info <| match counts[InputCategory.Url], counts[InputCategory.Command] with @@ -62,7 +62,7 @@ module Orchestrator = | Ok () -> if urlIndex > 1 then // Don't sleep for the first URL. settings.SleepSecondsBetweenURLs - |> String.pluralize "second" "seconds" + |> String.pluralizeS "second" |> fun secondsLabel -> sleep (fun seconds -> $"Sleeping for {seconds} {secondsLabel}...") diff --git a/src/CCVTAC.Main/ResultTracker.fs b/src/CCVTAC.Main/ResultTracker.fs index ff717b2..8a7f4b5 100644 --- a/src/CCVTAC.Main/ResultTracker.fs +++ b/src/CCVTAC.Main/ResultTracker.fs @@ -43,15 +43,15 @@ type ResultTracker<'a>(printer: Printer) = if Num.isZero failures.Count then printer.Debug "No failures in batch." else - let failureLabel = String.pluralize "failure" "failures" failures.Count + let failureLabel = String.pluralizeS "failure" failures.Count printer.Info $"%d{failures.Count} %s{failureLabel} in this batch:" for pair in failures do printer.Warning $"- %s{pair.Key}: %s{pair.Value}" /// Prints the output for the current application session. member _.PrintSessionSummary() : unit = - let successLabel = String.pluralize "success" "successes" successCount - let failureLabel = String.pluralize "failure" "failures" failures.Count + let successLabel = String.pluralizeEs "success" successCount + let failureLabel = String.pluralizeS "failure" failures.Count printer.Info $"Quitting with %d{successCount} %s{successLabel} and %d{failures.Count} %s{failureLabel}." diff --git a/src/CCVTAC.Main/Settings/Settings.fs b/src/CCVTAC.Main/Settings/Settings.fs index e0fa905..6ded58d 100644 --- a/src/CCVTAC.Main/Settings/Settings.fs +++ b/src/CCVTAC.Main/Settings/Settings.fs @@ -84,7 +84,7 @@ module Settings = | false -> "OFF" let simplePluralize label count = - String.pluralize label $"{label}s" count + String.pluralizeS label count |> sprintf "%d %s" count let tagDetectionPatternCount (patterns: TagDetectionPatterns) = @@ -129,7 +129,7 @@ module Settings = Printer.PrintTable table - module Validation = + module Validation' = open System.IO let validate settings = @@ -163,16 +163,17 @@ module Settings = Ok settings module IO = + open Validation' open System.IO open System.Text.Json open System.Text.Unicode open System.Text.Encodings.Web - open Validation let deserialize<'a> (json: string) : Result<'a, string> = let options = JsonSerializerOptions() options.AllowTrailingCommas <- true options.ReadCommentHandling <- JsonCommentHandling.Skip + options.AllowDuplicateProperties <- false try match JsonSerializer.Deserialize<'a>(json, options) with | null -> Error "Could not deserialize the settings JSON" @@ -208,7 +209,7 @@ module Settings = writeFile fileInfo defaultSettings module LiveUpdating = - open Validation + open Validation' let toggleSplitChapters settings = { settings with SplitChapters = not settings.SplitChapters } diff --git a/src/CCVTAC.Tests/CCVTAC.Tests.fsproj b/src/CCVTAC.Tests/CCVTAC.Tests.fsproj index 48b79b1..6a9caa7 100644 --- a/src/CCVTAC.Tests/CCVTAC.Tests.fsproj +++ b/src/CCVTAC.Tests/CCVTAC.Tests.fsproj @@ -14,7 +14,7 @@ - + From d7239de43b0a8ce6edee2e799bfcc62e0b4e5962 Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:14:08 +0900 Subject: [PATCH 02/10] Update packages --- src/CCVTAC.Main/CCVTAC.Main.fsproj | 4 ++-- src/CCVTAC.Tests/CCVTAC.Tests.fsproj | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CCVTAC.Main/CCVTAC.Main.fsproj b/src/CCVTAC.Main/CCVTAC.Main.fsproj index 4a588d2..47cdf54 100644 --- a/src/CCVTAC.Main/CCVTAC.Main.fsproj +++ b/src/CCVTAC.Main/CCVTAC.Main.fsproj @@ -43,9 +43,9 @@ - + - + diff --git a/src/CCVTAC.Tests/CCVTAC.Tests.fsproj b/src/CCVTAC.Tests/CCVTAC.Tests.fsproj index 6a9caa7..6063cee 100644 --- a/src/CCVTAC.Tests/CCVTAC.Tests.fsproj +++ b/src/CCVTAC.Tests/CCVTAC.Tests.fsproj @@ -15,17 +15,17 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + From affa2dc4638bd6eb9aceb4b8f88ca4ad6039bf3b Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Mon, 16 Mar 2026 16:03:35 +0900 Subject: [PATCH 03/10] Add videoIdFromMatch func --- src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs index 90e4ca7..76f772d 100644 --- a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs +++ b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs @@ -24,6 +24,8 @@ module TaggingSet = let allFiles t = t.AudioFiles @ [t.JsonFile; t.ImageFile] + let videoIdFromMatch (m : Match) = m.Groups[1].Value + let private create v a j i = { VideoId = v AudioFiles = a |> List.ofSeq @@ -88,7 +90,7 @@ module TaggingSet = |> List.ofSeq |> List.choose isRelevantFile |> List.map extractFileNameMatch - |> List.groupBy _.Groups[1].Value // By video ID + |> List.groupBy videoIdFromMatch |> List.map (extractFileNames >> createValidated) |> List.sequenceResultA |! List.collect id From 2f37c699c269896ddced8c658857d488a1a21844 Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Mon, 16 Mar 2026 18:00:59 +0900 Subject: [PATCH 04/10] Use pipe --- src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs index 76f772d..90971e4 100644 --- a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs +++ b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs @@ -79,7 +79,7 @@ module TaggingSet = let fileNamesHavingVideoIdsRegex = Regex(@".+\[([\w_\-]{11})\](?:.*)?\.(\w+)", RegexOptions.Compiled) - Rgx.trySuccessMatch fileNamesHavingVideoIdsRegex fileName + fileName |> Rgx.trySuccessMatch fileNamesHavingVideoIdsRegex let extractFileNameMatch = Rgx.fstCapture From 867825413e9f38e13ef152948fd68e999190c263 Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Tue, 17 Mar 2026 20:51:18 +0900 Subject: [PATCH 05/10] Relocate videoIdFromMatch --- src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs index 90971e4..8fba8fa 100644 --- a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs +++ b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs @@ -24,8 +24,6 @@ module TaggingSet = let allFiles t = t.AudioFiles @ [t.JsonFile; t.ImageFile] - let videoIdFromMatch (m : Match) = m.Groups[1].Value - let private create v a j i = { VideoId = v AudioFiles = a |> List.ofSeq @@ -81,15 +79,17 @@ module TaggingSet = fileName |> Rgx.trySuccessMatch fileNamesHavingVideoIdsRegex - let extractFileNameMatch = Rgx.fstCapture + let fileNameFromMatch = Rgx.fstCapture + + let videoIdFromMatch (m : Match) = m.Groups[1].Value - let extractFileNames (x, matches: Match list) : 'a * string list = - x, matches |> List.map _.Groups[0].Value + let extractFileNames (x, ms: Match list) : 'a * string list = + x, ms |> List.map _.Groups[0].Value filePaths |> List.ofSeq |> List.choose isRelevantFile - |> List.map extractFileNameMatch + |> List.map fileNameFromMatch |> List.groupBy videoIdFromMatch |> List.map (extractFileNames >> createValidated) |> List.sequenceResultA From b9267d4906a356153086f3c84b065aeefcdfcd94 Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Fri, 20 Mar 2026 11:24:25 +0900 Subject: [PATCH 06/10] Update packages --- src/CCVTAC.Main/CCVTAC.Main.fsproj | 4 ++-- src/CCVTAC.Tests/CCVTAC.Tests.fsproj | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CCVTAC.Main/CCVTAC.Main.fsproj b/src/CCVTAC.Main/CCVTAC.Main.fsproj index 47cdf54..9f84388 100644 --- a/src/CCVTAC.Main/CCVTAC.Main.fsproj +++ b/src/CCVTAC.Main/CCVTAC.Main.fsproj @@ -40,12 +40,12 @@ - + - + diff --git a/src/CCVTAC.Tests/CCVTAC.Tests.fsproj b/src/CCVTAC.Tests/CCVTAC.Tests.fsproj index 6063cee..09bb393 100644 --- a/src/CCVTAC.Tests/CCVTAC.Tests.fsproj +++ b/src/CCVTAC.Tests/CCVTAC.Tests.fsproj @@ -14,18 +14,18 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + From 4cd5ddbcd8040b284d9d8e8c9eb6142ca1122fef Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Fri, 20 Mar 2026 11:26:19 +0900 Subject: [PATCH 07/10] Use List.mapSnds, etc. --- .../PostProcessing/Tagging/TaggingSet.fs | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs index 8fba8fa..cc1acef 100644 --- a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs +++ b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs @@ -70,27 +70,23 @@ module TaggingSet = /// Any validation errors will be accumulated and return in an Error. let createSets filePaths : Result = if Seq.isEmpty filePaths then - Error ["No filepaths to create a tagging set were provided."] + Error ["No file paths to create a tagging set were provided."] else - let isRelevantFile fileName = + let isRelevantFile fileName : Match option = // Regex group 0 is the full filename, and group 1 contains the video ID. - let fileNamesHavingVideoIdsRegex = + let fileNamesHavingVideoIdsRgx = Regex(@".+\[([\w_\-]{11})\](?:.*)?\.(\w+)", RegexOptions.Compiled) - fileName |> Rgx.trySuccessMatch fileNamesHavingVideoIdsRegex + fileName |> Rgx.trySuccessMatch fileNamesHavingVideoIdsRgx - let fileNameFromMatch = Rgx.fstCapture - - let videoIdFromMatch (m : Match) = m.Groups[1].Value - - let extractFileNames (x, ms: Match list) : 'a * string list = - x, ms |> List.map _.Groups[0].Value + let fileName (m: Match) = m.Groups[0].Value + let videoId (m: Match) = m.Groups[1].Value filePaths |> List.ofSeq |> List.choose isRelevantFile - |> List.map fileNameFromMatch - |> List.groupBy videoIdFromMatch - |> List.map (extractFileNames >> createValidated) + |> List.groupBy videoId + |> List.map (List.mapSnds fileName) + |> List.map createValidated |> List.sequenceResultA |! List.collect id From ca6a057f1466be731817201c7cd2d1d76bc7d054 Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Fri, 20 Mar 2026 17:57:23 +0900 Subject: [PATCH 08/10] Update package; use new List.mapSnds --- src/CCVTAC.Main/CCVTAC.Main.fsproj | 2 +- src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs | 2 +- src/CCVTAC.Tests/CCVTAC.Tests.fsproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CCVTAC.Main/CCVTAC.Main.fsproj b/src/CCVTAC.Main/CCVTAC.Main.fsproj index 9f84388..8b4440f 100644 --- a/src/CCVTAC.Main/CCVTAC.Main.fsproj +++ b/src/CCVTAC.Main/CCVTAC.Main.fsproj @@ -40,7 +40,7 @@ - + diff --git a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs index cc1acef..5f97b48 100644 --- a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs +++ b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs @@ -86,7 +86,7 @@ module TaggingSet = |> List.ofSeq |> List.choose isRelevantFile |> List.groupBy videoId - |> List.map (List.mapSnds fileName) + |> List.mapSnds fileName |> List.map createValidated |> List.sequenceResultA |! List.collect id diff --git a/src/CCVTAC.Tests/CCVTAC.Tests.fsproj b/src/CCVTAC.Tests/CCVTAC.Tests.fsproj index 09bb393..800c80a 100644 --- a/src/CCVTAC.Tests/CCVTAC.Tests.fsproj +++ b/src/CCVTAC.Tests/CCVTAC.Tests.fsproj @@ -14,7 +14,7 @@ - + From f4db75effba9959f73c639870dd75c2f035d3522 Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Sat, 21 Mar 2026 18:01:14 +0900 Subject: [PATCH 09/10] Update package --- src/CCVTAC.Main/CCVTAC.Main.fsproj | 2 +- src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs | 4 ++-- src/CCVTAC.Tests/CCVTAC.Tests.fsproj | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CCVTAC.Main/CCVTAC.Main.fsproj b/src/CCVTAC.Main/CCVTAC.Main.fsproj index 8b4440f..a99b120 100644 --- a/src/CCVTAC.Main/CCVTAC.Main.fsproj +++ b/src/CCVTAC.Main/CCVTAC.Main.fsproj @@ -40,7 +40,7 @@ - + diff --git a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs index 5f97b48..2ebad88 100644 --- a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs +++ b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs @@ -80,13 +80,13 @@ module TaggingSet = fileName |> Rgx.trySuccessMatch fileNamesHavingVideoIdsRgx let fileName (m: Match) = m.Groups[0].Value - let videoId (m: Match) = m.Groups[1].Value + let videoId (m: Match) = m.Groups[1].Value filePaths |> List.ofSeq |> List.choose isRelevantFile |> List.groupBy videoId - |> List.mapSnds fileName + |> List.mapSnd fileName |> List.map createValidated |> List.sequenceResultA |! List.collect id diff --git a/src/CCVTAC.Tests/CCVTAC.Tests.fsproj b/src/CCVTAC.Tests/CCVTAC.Tests.fsproj index 800c80a..d868ec7 100644 --- a/src/CCVTAC.Tests/CCVTAC.Tests.fsproj +++ b/src/CCVTAC.Tests/CCVTAC.Tests.fsproj @@ -14,7 +14,7 @@ - + From d1faaa13912d3a008dad9a844b16aa04b1ac7ef5 Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Sat, 21 Mar 2026 21:13:17 +0900 Subject: [PATCH 10/10] Rename binding --- src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs index 2ebad88..100a81b 100644 --- a/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs +++ b/src/CCVTAC.Main/PostProcessing/Tagging/TaggingSet.fs @@ -30,7 +30,7 @@ module TaggingSet = JsonFile = j ImageFile = i } - let private createValidated (videoId, files) : Result = + let private createValidated (videoId, fileNames) : Result = let ensureNotEmpty xs errorMsg : Validation<'a list, string> = if List.isNotEmpty xs then Ok xs @@ -48,11 +48,11 @@ module TaggingSet = | NonNull empty when String.hasNoText empty -> false | NonNull ext -> Files.audioFileExts |> List.containsIgnoreCase ext - let audioFiles = files |> List.filter hasSupportedAudioExt - let jsonFiles = files |> Files.filterByExt Files.jsonFileExt + let audioFiles = fileNames |> List.filter hasSupportedAudioExt + let jsonFiles = fileNames |> Files.filterByExt Files.jsonFileExt let imageFiles = Files.imageFileExts - |> List.collect (fun ext -> files |> Files.filterByExt ext) + |> List.collect (fun ext -> fileNames |> Files.filterByExt ext) Validation.map3 (fun a j i -> create videoId a j i)