From 3091d844c0fe9a950d82755434a39fce3c2e113e Mon Sep 17 00:00:00 2001 From: Marc Brugger Date: Fri, 27 Jun 2025 13:35:15 +0200 Subject: [PATCH] fix: parse pocket new CSV format (#1112) * fix pocket parsing error Signed-off-by: bakito * add tests forpocket csv Signed-off-by: bakito * Use file name from test case * fix lint ant test issues Signed-off-by: bakito --------- Signed-off-by: bakito Co-authored-by: Felipe Martin <812088+fmartingr@users.noreply.github.com> --- internal/cmd/pocket.go | 13 ++++--- internal/cmd/pocket_test.go | 76 +++++++++++++++++++++++++++++++++++++ testdata/pocket-new.csv | 2 + testdata/pocket-old.csv | 2 + 4 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 internal/cmd/pocket_test.go create mode 100644 testdata/pocket-new.csv create mode 100644 testdata/pocket-old.csv diff --git a/internal/cmd/pocket.go b/internal/cmd/pocket.go index 317b270b..884dfd32 100644 --- a/internal/cmd/pocket.go +++ b/internal/cmd/pocket.go @@ -10,7 +10,6 @@ import ( "regexp" "slices" "strconv" - "strings" "time" "github.com/PuerkitoBio/goquery" @@ -123,19 +122,23 @@ func parseCsvExport(ctx context.Context, db model.DB, srcFile *os.File) []model. os.Exit(1) } + var titleIdx, urlIdx, timeAddedIdx, tagsIdx int for i, cols := range records { // Check and skip header if i == 0 { - expected := []string{"title", "url", "time_added", "cursor", "tags", "status"} - if slices.Compare(cols, expected) != 0 { - cError.Printf("Invalid CSV format. Header must be: %s\n", strings.Join(expected, ",")) + titleIdx = slices.Index(cols, "title") + urlIdx = slices.Index(cols, "url") + timeAddedIdx = slices.Index(cols, "time_added") + tagsIdx = slices.Index(cols, "tags") + if titleIdx == -1 || urlIdx == -1 || timeAddedIdx == -1 || tagsIdx == -1 { + cError.Printf("Invalid CSV format. Header must contain: title, url, time_added, tags\n") os.Exit(1) } continue } // Get metadata - title, url, timeAdded, tags, err := verifyMetadata(cols[0], cols[1], cols[2], cols[4]) + title, url, timeAdded, tags, err := verifyMetadata(cols[titleIdx], cols[urlIdx], cols[timeAddedIdx], cols[tagsIdx]) if err != nil { cError.Printf("Skip %s: %v\n", url, err) continue diff --git a/internal/cmd/pocket_test.go b/internal/cmd/pocket_test.go new file mode 100644 index 00000000..3adf044e --- /dev/null +++ b/internal/cmd/pocket_test.go @@ -0,0 +1,76 @@ +package cmd + +import ( + "context" + "os" + "path/filepath" + "testing" + + "github.com/go-shiori/shiori/internal/database" +) + +func Test_parseCsvExport_old_format(t *testing.T) { + tests := []struct { + name string + fileName string + }{ + { + name: "Test old file format", + fileName: "pocket-old.csv", + }, + { + name: "Test new file format", + fileName: "pocket-new.csv", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + file, err := os.Open("../../testdata/" + tt.fileName) + if err != nil { + t.Error(err.Error()) + } + defer file.Close() + ctx := context.TODO() + + tmpDir, err := os.MkdirTemp("", "shiori-test-*") + if err != nil { + t.Fatalf("failed to create temp dir: %v", err) + } + defer os.RemoveAll(tmpDir) + + dbPath := filepath.Join(tmpDir, "shiori.db") + db, err := database.OpenSQLiteDatabase(ctx, dbPath) + if err != nil { + t.Fatalf("failed to open sqlite database: %v", err) + } + + if err := db.Migrate(ctx); err != nil { + t.Fatalf("failed to migrate sqlite database: %v", err) + } + + bookmarks := parseCsvExport(ctx, db, file) + if len(bookmarks) != 1 { + t.Errorf("Expected 1 bookmarks, got %d", len(bookmarks)) + } + bm := bookmarks[0] + if bm.Title != "Shiori" { + t.Errorf("Expected Title Shiori got %s", bm.URL) + } + if bm.URL != "https://github.com/go-shiori/shiori" { + t.Errorf("Expected URL https://github.com/go-shiori/shiori, got %s", bm.URL) + } + if len(bm.Tags) != 1 { + t.Errorf("Expected 1 tags, got %d", len(bm.Tags)) + } + if bm.Tags[0].Name != "shiori" { + t.Errorf("Expected tag shiori, got %s", bm.Tags[0].Name) + } + if bm.CreatedAt == "" { + t.Error("Expected CreatedAt to be not empty") + } + if bm.ModifiedAt == "" { + t.Error("Expected CreatedAt to be not empty") + } + }) + } +} diff --git a/testdata/pocket-new.csv b/testdata/pocket-new.csv new file mode 100644 index 00000000..906e5e7d --- /dev/null +++ b/testdata/pocket-new.csv @@ -0,0 +1,2 @@ +title,url,time_added,tags,status +Shiori,https://github.com/go-shiori/shiori,1541343937,shiori,unread \ No newline at end of file diff --git a/testdata/pocket-old.csv b/testdata/pocket-old.csv new file mode 100644 index 00000000..083e09e8 --- /dev/null +++ b/testdata/pocket-old.csv @@ -0,0 +1,2 @@ +title,url,time_added,cursor,tags,status +Shiori,https://github.com/go-shiori/shiori,1541343937,,shiori,unread \ No newline at end of file