From 45f86451fb08326b312ee83e60744ef1ac70ae5c Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 26 Apr 2026 23:42:02 -0700 Subject: [PATCH] feat: persist thread comments --- internal/store/comments.go | 42 +++++++++++++++++++++++++++++++++ internal/store/comments_test.go | 39 ++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 internal/store/comments.go create mode 100644 internal/store/comments_test.go diff --git a/internal/store/comments.go b/internal/store/comments.go new file mode 100644 index 0000000..6600a4e --- /dev/null +++ b/internal/store/comments.go @@ -0,0 +1,42 @@ +package store + +import ( + "context" + "fmt" +) + +type Comment struct { + ID int64 `json:"id"` + ThreadID int64 `json:"thread_id"` + GitHubID string `json:"github_id"` + CommentType string `json:"comment_type"` + AuthorLogin string `json:"author_login,omitempty"` + AuthorType string `json:"author_type,omitempty"` + Body string `json:"body"` + IsBot bool `json:"is_bot"` + RawJSON string `json:"-"` + CreatedAtGitHub string `json:"created_at_gh,omitempty"` + UpdatedAtGitHub string `json:"updated_at_gh,omitempty"` +} + +func (s *Store) UpsertComment(ctx context.Context, comment Comment) (int64, error) { + var id int64 + err := s.db.QueryRowContext(ctx, ` + insert into comments(thread_id, github_id, comment_type, author_login, author_type, body, is_bot, raw_json, created_at_gh, updated_at_gh) + values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + on conflict(thread_id, comment_type, github_id) do update set + author_login=excluded.author_login, + author_type=excluded.author_type, + body=excluded.body, + is_bot=excluded.is_bot, + raw_json=excluded.raw_json, + created_at_gh=excluded.created_at_gh, + updated_at_gh=excluded.updated_at_gh + returning id + `, comment.ThreadID, comment.GitHubID, comment.CommentType, nullString(comment.AuthorLogin), nullString(comment.AuthorType), comment.Body, + boolInt(comment.IsBot), comment.RawJSON, nullString(comment.CreatedAtGitHub), nullString(comment.UpdatedAtGitHub)).Scan(&id) + if err != nil { + return 0, fmt.Errorf("upsert comment: %w", err) + } + return id, nil +} diff --git a/internal/store/comments_test.go b/internal/store/comments_test.go new file mode 100644 index 0000000..7a5fa69 --- /dev/null +++ b/internal/store/comments_test.go @@ -0,0 +1,39 @@ +package store + +import ( + "context" + "path/filepath" + "testing" +) + +func TestUpsertComment(t *testing.T) { + ctx := context.Background() + st, err := Open(ctx, filepath.Join(t.TempDir(), "gitcrawl.db")) + if err != nil { + t.Fatalf("open store: %v", err) + } + defer st.Close() + + repoID, err := st.UpsertRepository(ctx, Repository{Owner: "openclaw", Name: "gitcrawl", FullName: "openclaw/gitcrawl", RawJSON: "{}", UpdatedAt: "2026-04-26T00:00:00Z"}) + if err != nil { + t.Fatalf("repo: %v", err) + } + threadID, err := st.UpsertThread(ctx, Thread{ + RepoID: repoID, GitHubID: "1", Number: 1, Kind: "issue", State: "open", + Title: "download stalls", HTMLURL: "https://github.com/openclaw/gitcrawl/issues/1", + LabelsJSON: "[]", AssigneesJSON: "[]", RawJSON: "{}", ContentHash: "hash", UpdatedAt: "2026-04-26T00:00:00Z", + }) + if err != nil { + t.Fatalf("thread: %v", err) + } + id, err := st.UpsertComment(ctx, Comment{ + ThreadID: threadID, GitHubID: "c1", CommentType: "issue_comment", + AuthorLogin: "vincentkoc", Body: "same bug here", RawJSON: "{}", CreatedAtGitHub: "2026-04-26T00:00:00Z", + }) + if err != nil { + t.Fatalf("comment: %v", err) + } + if id == 0 { + t.Fatal("expected comment id") + } +}