From f4d0d29635a90eb71f0b258315cd8ec249830c0e Mon Sep 17 00:00:00 2001 From: Thomas Rademaker Date: Thu, 16 Apr 2026 12:26:29 -0400 Subject: [PATCH] better comments --- appview/database/models.go | 33 +++++++++++++++-------------- appview/firehose.go | 2 +- appview/handlers/comment.go | 41 ++++++++++++++++++++++--------------- appview/indexer/comment.go | 5 ++++- appview/indexer/indexer.go | 4 ++-- 5 files changed, 50 insertions(+), 35 deletions(-) diff --git a/appview/database/models.go b/appview/database/models.go index 56fff0c..4e100aa 100644 --- a/appview/database/models.go +++ b/appview/database/models.go @@ -24,21 +24,24 @@ type Subscription struct { func (Subscription) TableName() string { return "subscriptions" } type Comment struct { - ID uint `gorm:"primaryKey" json:"-"` - DID string `gorm:"column:did;size:255;not null;index:idx_comments_did_rkey,unique;index:idx_comments_did" json:"did"` - Rkey string `gorm:"size:512;not null;index:idx_comments_did_rkey,unique" json:"rkey"` - ATURI string `gorm:"column:at_uri;size:1024;index;not null" json:"at_uri"` - FeedID int64 `gorm:"not null;index:idx_comments_episode" json:"feed_id"` - EpisodeID int64 `gorm:"not null;index:idx_comments_episode" json:"episode_id"` - EpisodeGuid string `gorm:"size:512" json:"episode_guid"` - PodcastGuid string `gorm:"size:512" json:"podcast_guid"` - Text string `gorm:"type:text;not null" json:"text"` - TimestampS *int `gorm:"index" json:"timestamp_s"` - ReplyRoot string `gorm:"size:1024;index:idx_comments_reply_root" json:"reply_root"` - ReplyParent string `gorm:"size:1024" json:"reply_parent"` - Facets []byte `gorm:"type:jsonb" json:"facets"` - CreatedAt string `gorm:"size:64;not null" json:"created_at"` - IndexedAt time.Time `gorm:"autoCreateTime" json:"-"` + ID uint `gorm:"primaryKey" json:"-"` + DID string `gorm:"column:did;size:255;not null;index:idx_comments_did_rkey,unique;index:idx_comments_did" json:"did"` + Rkey string `gorm:"size:512;not null;index:idx_comments_did_rkey,unique" json:"rkey"` + CID string `gorm:"column:cid;size:256" json:"cid"` + ATURI string `gorm:"column:at_uri;size:1024;index;not null" json:"at_uri"` + FeedID int64 `gorm:"not null;index:idx_comments_episode" json:"feed_id"` + EpisodeID int64 `gorm:"not null;index:idx_comments_episode" json:"episode_id"` + EpisodeGuid string `gorm:"size:512" json:"episode_guid"` + PodcastGuid string `gorm:"size:512" json:"podcast_guid"` + Text string `gorm:"type:text;not null" json:"text"` + TimestampS *int `gorm:"index" json:"timestamp_s"` + ReplyRoot string `gorm:"size:1024;index:idx_comments_reply_root" json:"reply_root"` + ReplyRootCID string `gorm:"column:reply_root_cid;size:256" json:"reply_root_cid"` + ReplyParent string `gorm:"size:1024" json:"reply_parent"` + ReplyParentCID string `gorm:"column:reply_parent_cid;size:256" json:"reply_parent_cid"` + Facets []byte `gorm:"type:jsonb" json:"facets"` + CreatedAt string `gorm:"size:64;not null" json:"created_at"` + IndexedAt time.Time `gorm:"autoCreateTime" json:"-"` } func (Comment) TableName() string { return "comments" } diff --git a/appview/firehose.go b/appview/firehose.go index 6669e37..b13d256 100644 --- a/appview/firehose.go +++ b/appview/firehose.go @@ -122,7 +122,7 @@ func (srv *Server) handleCommit(ctx context.Context, evt *comatproto.SyncSubscri srv.logger.Warn("nil record payload", "path", op.Path) continue } - if err := srv.indexer.IndexRecord(ctx, evt.Repo, collectionName, rkey.String(), *recCBOR); err != nil { + if err := srv.indexer.IndexRecord(ctx, evt.Repo, collectionName, rkey.String(), recCID.String(), *recCBOR); err != nil { srv.logger.Warn("failed to index record", "err", err, "path", op.Path) } case repomgr.EvtKindDeleteRecord: diff --git a/appview/handlers/comment.go b/appview/handlers/comment.go index b777332..674e38c 100644 --- a/appview/handlers/comment.go +++ b/appview/handlers/comment.go @@ -16,15 +16,18 @@ type commentEpisodeRef struct { } type commentResponse struct { - DID string `json:"did"` - Rkey string `json:"rkey"` - Episode commentEpisodeRef `json:"episode"` - Text string `json:"text"` - Timestamp *int `json:"timestamp,omitempty"` - ReplyRoot string `json:"reply_root,omitempty"` - ReplyParent string `json:"reply_parent,omitempty"` - Facets json.RawMessage `json:"facets,omitempty"` - CreatedAt string `json:"created_at"` + DID string `json:"did"` + Rkey string `json:"rkey"` + CID string `json:"cid,omitempty"` + Episode commentEpisodeRef `json:"episode"` + Text string `json:"text"` + Timestamp *int `json:"timestamp,omitempty"` + ReplyRoot string `json:"reply_root,omitempty"` + ReplyRootCID string `json:"reply_root_cid,omitempty"` + ReplyParent string `json:"reply_parent,omitempty"` + ReplyParentCID string `json:"reply_parent_cid,omitempty"` + Facets json.RawMessage `json:"facets,omitempty"` + CreatedAt string `json:"created_at"` } func toCommentResponse(row database.Comment) commentResponse { @@ -36,18 +39,21 @@ func toCommentResponse(row database.Comment) commentResponse { return commentResponse{ DID: row.DID, Rkey: row.Rkey, + CID: row.CID, Episode: commentEpisodeRef{ FeedID: row.FeedID, EpisodeID: row.EpisodeID, EpisodeGuid: row.EpisodeGuid, PodcastGuid: row.PodcastGuid, }, - Text: row.Text, - Timestamp: row.TimestampS, - ReplyRoot: row.ReplyRoot, - ReplyParent: row.ReplyParent, - Facets: facets, - CreatedAt: row.CreatedAt, + Text: row.Text, + Timestamp: row.TimestampS, + ReplyRoot: row.ReplyRoot, + ReplyRootCID: row.ReplyRootCID, + ReplyParent: row.ReplyParent, + ReplyParentCID: row.ReplyParentCID, + Facets: facets, + CreatedAt: row.CreatedAt, } } @@ -101,8 +107,11 @@ func (h *Handlers) GetCommentThread(c echo.Context) error { reqDID := requestingDID(c) + rootQuery := h.db.WithContext(c.Request().Context()).Where("at_uri = ?", uri) + rootQuery = h.excludeBlockedDIDs(rootQuery, reqDID, "did") + var root database.Comment - if err := h.db.WithContext(c.Request().Context()).Where("at_uri = ?", uri).First(&root).Error; err != nil { + if err := rootQuery.First(&root).Error; err != nil { return writeError(c, http.StatusNotFound, "NotFound", "comment not found") } diff --git a/appview/indexer/comment.go b/appview/indexer/comment.go index 01841b3..b0ae367 100644 --- a/appview/indexer/comment.go +++ b/appview/indexer/comment.go @@ -7,7 +7,7 @@ import ( "tangled.org/sparrowtek.com/effem-AppView/appview/database" ) -func (idx *Indexer) indexComment(ctx context.Context, did, rkey string, rec map[string]any) error { +func (idx *Indexer) indexComment(ctx context.Context, did, rkey, cid string, rec map[string]any) error { episode, ok := asMap(rec["episode"]) if !ok { return fmt.Errorf("comment missing episode object") @@ -24,6 +24,7 @@ func (idx *Indexer) indexComment(ctx context.Context, did, rkey string, rec map[ comment := database.Comment{ DID: did, Rkey: rkey, + CID: cid, ATURI: fmt.Sprintf("at://%s/xyz.effem.feed.comment/%s", did, rkey), FeedID: feedID, EpisodeID: episodeID, @@ -42,9 +43,11 @@ func (idx *Indexer) indexComment(ctx context.Context, did, rkey string, rec map[ if reply, ok := asMap(rec["reply"]); ok { if root, ok := asMap(reply["root"]); ok { comment.ReplyRoot = asString(root["uri"]) + comment.ReplyRootCID = asString(root["cid"]) } if parent, ok := asMap(reply["parent"]); ok { comment.ReplyParent = asString(parent["uri"]) + comment.ReplyParentCID = asString(parent["cid"]) } } diff --git a/appview/indexer/indexer.go b/appview/indexer/indexer.go index 29a6a53..83e8cd3 100644 --- a/appview/indexer/indexer.go +++ b/appview/indexer/indexer.go @@ -20,7 +20,7 @@ func New(db *gorm.DB, logger *slog.Logger) *Indexer { return &Indexer{db: db, logger: logger.With("component", "indexer")} } -func (idx *Indexer) IndexRecord(ctx context.Context, did, collection, rkey string, data []byte) error { +func (idx *Indexer) IndexRecord(ctx context.Context, did, collection, rkey, cid string, data []byte) error { rec, err := atdata.UnmarshalCBOR(data) if err != nil { return fmt.Errorf("decoding record cbor: %w", err) @@ -30,7 +30,7 @@ func (idx *Indexer) IndexRecord(ctx context.Context, did, collection, rkey strin case "xyz.effem.feed.subscription": return idx.indexSubscription(ctx, did, rkey, rec) case "xyz.effem.feed.comment": - return idx.indexComment(ctx, did, rkey, rec) + return idx.indexComment(ctx, did, rkey, cid, rec) case "xyz.effem.feed.recommendation": return idx.indexRecommendation(ctx, did, rkey, rec) case "xyz.effem.feed.list": -- 2.51.2