From 4737baa288486ded7ca84b7a0029e00391812f11 Mon Sep 17 00:00:00 2001 From: jim Date: Thu, 7 May 2026 15:56:53 -0500 Subject: [PATCH] fix: keep '.' as needs-processing sentinel, normalize real-dot replies Previous fix removed '.' from the GetRepliesWithFilledText SELECT, which broke processing of legacy null-substitute rows that need to be re-fetched. Restored '.' in the SELECT. To avoid the infinite loop when an actual API reply is the literal string ".", normalize it to ". " (dot + trailing space) inside UpdateNoteReplyText so the stored value no longer matches the sentinel. Also extended the fan-out UPDATE guard to match the SELECT criteria (NULL / '' / '.') so legacy '.' rows in other reblog copies can be filled in too. The guard still refuses to overwrite '?' or already-fetched text. Co-Authored-By: Claude Sonnet 4.6 --- URLNotesGrabberCORE/DataAccess.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/URLNotesGrabberCORE/DataAccess.cs b/URLNotesGrabberCORE/DataAccess.cs index d8bf849..9448e7c 100644 --- a/URLNotesGrabberCORE/DataAccess.cs +++ b/URLNotesGrabberCORE/DataAccess.cs @@ -873,7 +873,7 @@ namespace URLNotesGrabberCORE INNER JOIN Notes N ON N.PostID = P.PostID AND N.RootBlogName = P.BlogName WHERE P.NotFound = 0 AND N.type = 'reply' - AND (N.replyText IS NULL OR N.replyText = '') + AND (N.replyText IS NULL OR N.replyText = '' OR N.replyText = '.') GROUP BY P.BlogName, P.PostID ORDER BY LatestTimestamp ASC"; @@ -1473,13 +1473,18 @@ namespace URLNotesGrabberCORE SQLiteConnection connection = new SQLiteConnection("Data Source=" + DBPath); int rowsAffected = 0; + // A bare "." collides with the "needs processing" sentinel in GetRepliesWithFilledText, which would loop the post forever. Store as ". " so the data is preserved but no longer matches the sentinel. + if (replyText == ".") + replyText = ". "; + try { connection.Open(); //string sql = "UPDATE Notes SET replyText = @replyText WHERE rootBlogName = @rootBlogName AND PostID = @PostID AND noteBlogName = @noteBlogName AND TimeStamp = @TimeStamp AND Type = 'reply'"; // Match on (noteBlogName, TimeStamp ±5s) only - a reply by a given blog at a given timestamp is the same reply across the original post and every reblog of it, so this fans out across reblog chains in one shot. Tolerance absorbs the ~1s drift between what -collect stored and what mode=conversation returns now. - string sql = "UPDATE Notes SET replyText = @replyText, DateModified = @dateModified WHERE noteBlogName = @noteBlogName AND ABS(TimeStamp - @TimeStamp) <= 5 AND Type = 'reply' AND (replyText IS NULL OR replyText = '')"; + // Only fan out to rows that match the SELECT criteria in GetRepliesWithFilledText (NULL/empty/legacy-'.'). Never overwrite '?' (confirmed-empty) or already-fetched text. + string sql = "UPDATE Notes SET replyText = @replyText, DateModified = @dateModified WHERE noteBlogName = @noteBlogName AND ABS(TimeStamp - @TimeStamp) <= 5 AND Type = 'reply' AND (replyText IS NULL OR replyText = '' OR replyText = '.')"; using (SQLiteCommand command = new SQLiteCommand(sql, connection)) { command.Parameters.AddWithValue("@replyText", replyText ?? "?");