4 Commits
Author SHA1 Message Date
jim 16147b273e docs: document default-mode .txt ingest field parsing in AGENTS.md
Note TraverseDirectory's recognized field prefixes, multi-line
Body/Downloaded files continuation, and how RootURL now gets
populated from both the .txt Reblog root url line and the API-based
--likes flow.
2026-07-16 10:43:16 -05:00
jim 5361bb78b8 Merge remote master into txt-validation branch 2026-07-16 10:42:28 -05:00
jim 21a5525094 Capture multi-line Body/Downloaded files in default .txt ingest mode
TraverseDirectory only ever read the single line immediately after
"Body:"/"Downloaded files:", silently dropping every continuation
line (multi-paragraph HTML bodies, multiple downloaded filenames).
Switch to an indexed line scan so those two fields collect lines
until the next recognized field prefix, matching how IngestMode.cs
already handles multi-line values.
2026-07-16 10:23:16 -05:00
jim 33839930e8 Parse Reblog root url in default .txt ingest mode
TraverseDirectory (the no-args ingest path) never read the "Reblog
root url:" line, so RootURL stayed unset even though AddPost/UpdatePost
already support it via the API-based --likes flow. New scraper output
now includes this field; wire it through both AddPost call sites.
2026-07-16 10:20:50 -05:00
3 changed files with 49 additions and 5 deletions
+1
View File
@@ -11,6 +11,7 @@
- `ResponseNotes.cs`: Tumblr API response models
- Round-robin API key rotation with rate-limit tracking
- Automatic console color assignment per API key for output differentiation
- No-argument mode (`Program.TraverseDirectory`) ingests `.txt` blog export files into `Posts` via `DataAccess.AddPost`. Recognized field prefixes live in `TraverseDirectoryFieldPrefixes`; `Body:` and `Downloaded files:` collect every following line up to the next recognized prefix (multi-line values). `RootURL` is populated from a `Reblog root url:` line the same way it's populated from the API-based `--likes` flow — both paths converge on `DataAccess.AddPost`'s `rootURL` parameter, which `UpdatePost` only overwrites when the incoming value is non-empty (existing `RootURL` is preserved otherwise)
## Developer Guidelines
+2
View File
@@ -37,6 +37,7 @@ namespace URLNotesGrabberCORE
public string reblogKey;
public string reblogName;
public string reblogURL;
public string rootURL;
public string slug;
public string summary;
public string tags;
@@ -60,6 +61,7 @@ namespace URLNotesGrabberCORE
reblogKey = ".";
reblogName = ".";
reblogURL = ".";
rootURL = ".";
slug = ".";
summary = ".";
tags = ".";
+46 -5
View File
@@ -1362,6 +1362,25 @@ if (shouldInsert)
}
// Field prefixes TraverseDirectory recognizes as the start of a new record field.
// Used to know where a multi-line Body/Downloaded files value ends.
private static readonly string[] TraverseDirectoryFieldPrefixes = new[]
{
"Post id:", "Reblog url:", "Reblog name:", "Reblog root url:", "Downloaded files:",
"Reblog key:", "Date:", "Body:", "Post url:", "Answer:", "Audio Caption:", "Blog Name:",
"Link:", "Photo Caption:", "Photo url:", "Question:", "Quote:", "Slug:", "Summary:",
"Tags:", "Title:"
};
private static bool IsTraverseDirectoryFieldLine(string line)
{
foreach (var prefix in TraverseDirectoryFieldPrefixes)
{
if (line.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) return true;
}
return false;
}
static void TraverseDirectory(string path, string outPath, List<string> contains, ref int postsAdded, string blogName = "", string startFromBlogName = "", bool logRecordImports = false)
{
DateTime directoryStart = DateTime.Now;
@@ -1398,8 +1417,10 @@ if (shouldInsert)
var urls = new List<string>();
var reblog = new ReblogRecord();
foreach (string line in File.ReadLines(file))
string[] fileLines = File.ReadAllLines(file);
for (int lineIndex = 0; lineIndex < fileLines.Length; lineIndex++)
{
string line = fileLines[lineIndex];
if (line.StartsWith("Post id:", StringComparison.OrdinalIgnoreCase))
{
if (reblog.reblogName != "." && reblog.postID != "." && reblog.date != "." && reblog.reblogURL != "." && reblog.downloadedFiles == ".")
@@ -1420,7 +1441,7 @@ if (shouldInsert)
DataAccess.AddPost(curDir, long.Parse(reblog.postID), reblog.reblogURL, reblog.date, reblog.postURL, reblog.slug, reblog.reblogKey,
reblog.reblogName, reblog.summary, reblog.quote, reblog.body, reblog.tags, reblog.link, reblog.photoURL,
reblog.photoCaption, reblog.downloadedFiles, reblog.audioCaption, reblog.question, reblog.answer,
reblog.title, false);
reblog.title, false, rootURL: reblog.rootURL);
recordImportStopwatch.Stop();
postsAdded++;
@@ -1445,9 +1466,21 @@ if (shouldInsert)
{
reblog.reblogName = line.Substring(13).Trim();
}
if (line.StartsWith(@"Reblog root url:", StringComparison.OrdinalIgnoreCase))
{
reblog.rootURL = line.Substring(16).Trim();
}
if (line.StartsWith(@"Downloaded files:", StringComparison.OrdinalIgnoreCase))
{
reblog.downloadedFiles = line.Substring(17).Trim();
var valueLines = new List<string> { line.Substring(17).Trim() };
int nextLineIndex = lineIndex + 1;
while (nextLineIndex < fileLines.Length && !IsTraverseDirectoryFieldLine(fileLines[nextLineIndex]))
{
valueLines.Add(fileLines[nextLineIndex]);
nextLineIndex++;
}
reblog.downloadedFiles = string.Join("\n", valueLines).Trim();
lineIndex = nextLineIndex - 1;
}
if (line.StartsWith(@"Reblog key:", StringComparison.OrdinalIgnoreCase))
{
@@ -1459,7 +1492,15 @@ if (shouldInsert)
}
if (line.StartsWith(@"Body:", StringComparison.OrdinalIgnoreCase))
{
reblog.body = line.Substring(6).Trim();
var valueLines = new List<string> { line.Substring(6).Trim() };
int nextLineIndex = lineIndex + 1;
while (nextLineIndex < fileLines.Length && !IsTraverseDirectoryFieldLine(fileLines[nextLineIndex]))
{
valueLines.Add(fileLines[nextLineIndex]);
nextLineIndex++;
}
reblog.body = string.Join("\n", valueLines).Trim();
lineIndex = nextLineIndex - 1;
}
if (line.StartsWith(@"Post url:", StringComparison.OrdinalIgnoreCase))
{
@@ -1548,7 +1589,7 @@ if (shouldInsert)
DataAccess.AddPost(curDir, long.Parse(reblog.postID), reblog.reblogURL, reblog.date, reblog.postURL, reblog.slug, reblog.reblogKey,
reblog.reblogName, reblog.summary, reblog.quote, reblog.body, reblog.tags, reblog.link, reblog.photoURL,
reblog.photoCaption, reblog.downloadedFiles, reblog.audioCaption, reblog.question, reblog.answer,
reblog.title, true);
reblog.title, true, rootURL: reblog.rootURL);
recordImportStopwatch.Stop();
postsAdded++;