diff --git a/URLNotesGrabberCORE/DataAccess.cs b/URLNotesGrabberCORE/DataAccess.cs index 2e0ef06..3ae316d 100644 --- a/URLNotesGrabberCORE/DataAccess.cs +++ b/URLNotesGrabberCORE/DataAccess.cs @@ -1515,7 +1515,7 @@ namespace URLNotesGrabberCORE return rowsAffected; } - public static void UpdateAllNoteReplyTextForPost(string rootBlogName, long postID, string replyText, string? DBPath = null) + public static int UpdateAllNoteReplyTextForPost(string rootBlogName, long postID, string replyText, string? DBPath = null) { DBPath ??= GetDefaultDbPath(); SQLiteConnection connection = new SQLiteConnection("Data Source=" + DBPath); @@ -1532,7 +1532,7 @@ namespace URLNotesGrabberCORE command.Parameters.AddWithValue("@rootBlogName", rootBlogName); command.Parameters.AddWithValue("@PostID", postID); int rowsAffected = command.ExecuteNonQuery(); - + if (rowsAffected == 0) { Console.WriteLine($"[UpdateAllNoteReplyTextForPost] INFO: No rows updated for {rootBlogName}/{postID} (rows not found or values unchanged)"); @@ -1543,6 +1543,8 @@ namespace URLNotesGrabberCORE { Console.WriteLine($"[UpdateAllNoteReplyTextForPost] Successfully updated {rowsAffected} row(s) for {rootBlogName}/{postID} with '{replyText}'"); } + + return rowsAffected; } } catch (Exception ex) @@ -1550,6 +1552,7 @@ namespace URLNotesGrabberCORE // Breakpoint here Console.WriteLine($"[UpdateAllNoteReplyTextForPost] Error updating reply text: {ex.Message}"); Console.WriteLine($"[UpdateAllNoteReplyTextForPost] StackTrace: {ex.StackTrace}"); + return 0; } finally { diff --git a/URLNotesGrabberCORE/Program.cs b/URLNotesGrabberCORE/Program.cs index f9a5c98..0817c12 100644 --- a/URLNotesGrabberCORE/Program.cs +++ b/URLNotesGrabberCORE/Program.cs @@ -459,6 +459,7 @@ namespace URLNotesGrabberCORE int emptyReplyCount = 0; long pageTimestamp = 0; int page = 0; + bool sawHealthyResponse = false; while (page < MaxPages) { @@ -478,6 +479,9 @@ namespace URLNotesGrabberCORE if (postsResponse?.meta?.status != 429) ApiKeyPool.MarkAvailable(key); + if (postsResponse?.meta?.status == 200) + sawHealthyResponse = true; + if (postsResponse?.response == null || postsResponse.response.notes == null || postsResponse.response.notes.Count == 0) { var prevColor = Console.ForegroundColor; @@ -488,16 +492,6 @@ namespace URLNotesGrabberCORE var raw = postsResponse?.rawJson ?? string.Empty; if (raw.Length > 500) raw = raw.Substring(0, 500) + "...[truncated]"; Console.WriteLine($"[Reply Text] raw: {raw}"); - - // First-page 200 OK with empty notes = post has no conversational notes per Tumblr. - // Mark all the post's replies '?' so the work queue stops handing this post back. - if (page == 1 && postsResponse?.meta?.status == 200) - { - Console.ForegroundColor = ConsoleColor.Yellow; - Console.WriteLine($"[Reply Text] Marking all replies for {blogName}/{postID} '?' (200 OK with no conversational notes)"); - Console.ForegroundColor = prevColor; - DataAccess.UpdateAllNoteReplyTextForPost(blogName, postID, "?"); - } break; } @@ -551,6 +545,18 @@ namespace URLNotesGrabberCORE pageTimestamp = lastNoteTimestamp; } + // If pagination finished without updating any reply rows but the API responded healthily + // at least once, mark the post's outstanding '.' replies '?' so the work queue releases it. + if (rowsUpdated == 0 && sawHealthyResponse) + { + var prevColor = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine($"[Reply Text] Marking outstanding replies for {blogName}/{postID} '?' (healthy 200 OK, no matching reply notes after {page} page(s))"); + Console.ForegroundColor = prevColor; + rowsUpdated = DataAccess.UpdateAllNoteReplyTextForPost(blogName, postID, "?"); + emptyReplyCount += rowsUpdated; + } + Console.WriteLine($"[Reply Text] Done {blogName}/{postID}: notes={replyCount}, rowsUpdated={rowsUpdated}, empty='?'={emptyReplyCount}, pages={page}"); } catch (Exception ex)