This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / appview / models / comment.go
4.2 kB 159 lines
1package models 2 3import ( 4 "fmt" 5 "strings" 6 "time" 7 8 comatproto "github.com/bluesky-social/indigo/api/atproto" 9 "github.com/bluesky-social/indigo/atproto/syntax" 10 typegen "github.com/whyrusleeping/cbor-gen" 11 "tangled.org/core/api/tangled" 12) 13 14type Comment struct { 15 Id int64 16 17 Did syntax.DID 18 Collection syntax.NSID 19 Rkey syntax.RecordKey 20 Cid syntax.CID 21 22 // record content 23 Subject comatproto.RepoStrongRef 24 Body tangled.MarkupMarkdown // markup body type. only markdown is supported right now 25 Created time.Time 26 ReplyTo *comatproto.RepoStrongRef // (optional) parent comment 27 PullRoundIdx *int // (optional) pull round number used when subject is sh.tangled.repo.pull 28 29 // store on db, but not on PDS 30 Edited *time.Time 31 Deleted *time.Time 32} 33 34func (c *Comment) AtUri() syntax.ATURI { 35 return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", c.Did, c.Collection, c.Rkey)) 36} 37 38func (c *Comment) StrongRef() comatproto.RepoStrongRef { 39 return comatproto.RepoStrongRef{ 40 Uri: c.AtUri().String(), 41 Cid: c.Cid.String(), 42 } 43} 44 45func (c *Comment) AsRecord() typegen.CBORMarshaler { 46 // can't convert to record for legacy types 47 if c.Collection != tangled.FeedCommentNSID { 48 return nil 49 } 50 var pullRoundIdx *int64 51 if c.PullRoundIdx != nil { 52 pullRoundIdx = new(int64) 53 *pullRoundIdx = int64(*c.PullRoundIdx) 54 } 55 return &tangled.FeedComment{ 56 Subject: &c.Subject, 57 Body: &tangled.FeedComment_Body{MarkupMarkdown: &c.Body}, 58 CreatedAt: c.Created.Format(time.RFC3339), 59 ReplyTo: c.ReplyTo, 60 PullRoundIdx: pullRoundIdx, 61 } 62} 63 64func (c *Comment) EditableBody() string { 65 if c.Body.Original != nil { 66 return *c.Body.Original 67 } 68 return c.Body.Text 69} 70 71func (c *Comment) IsLegacy() bool { 72 return c.Collection != tangled.FeedCommentNSID 73} 74 75func (c *Comment) IsTopLevel() bool { 76 return c.ReplyTo == nil 77} 78 79func (c *Comment) IsReply() bool { 80 return c.ReplyTo != nil 81} 82 83func (c *Comment) Validate() error { 84 // TODO: sanitize the body and then trim space 85 if sb := strings.TrimSpace(c.Body.Text); sb == "" { 86 return fmt.Errorf("body is empty after HTML sanitization") 87 } 88 89 // if it's for PR, PullSubmissionId should not be nil 90 subjectAt, err := syntax.ParseATURI(c.Subject.Uri) 91 if err != nil { 92 return fmt.Errorf("subject.uri is not valid at-uri: %w", err) 93 } 94 if subjectAt.Collection().String() == tangled.RepoPullNSID { 95 if c.PullRoundIdx == nil { 96 return fmt.Errorf("pullSubmissionId should not be nil when subject is sh.tangled.repo.pull") 97 } 98 } 99 return nil 100} 101 102func CommentFromRecord(did syntax.DID, rkey syntax.RecordKey, cid syntax.CID, record tangled.FeedComment) (*Comment, error) { 103 created, err := time.Parse(time.RFC3339, record.CreatedAt) 104 if err != nil { 105 created = time.Now() 106 } 107 108 if record.Subject == nil { 109 return nil, fmt.Errorf("subject can't be nil") 110 } 111 subjectAt, err := syntax.ParseATURI(record.Subject.Uri) 112 if err != nil { 113 return nil, fmt.Errorf("invalid subject uri: %w", err) 114 } 115 if _, err = syntax.ParseCID(record.Subject.Cid); err != nil { 116 return nil, fmt.Errorf("invalid subject cid: %w", err) 117 } 118 119 if subjectAt.Collection() == tangled.RepoPullNSID { 120 if record.PullRoundIdx == nil { 121 return nil, fmt.Errorf("pullRoundIdx can't be nil when subject is sh.tangled.repo.pull") 122 } 123 } 124 125 if record.Body == nil { 126 return nil, fmt.Errorf("body can't be nil") 127 } 128 if record.Body.MarkupMarkdown == nil { 129 return nil, fmt.Errorf("body should be markdown type") 130 } 131 132 if record.ReplyTo != nil { 133 if _, err = syntax.ParseATURI(record.ReplyTo.Uri); err != nil { 134 return nil, fmt.Errorf("invalid replyTo uri: %w", err) 135 } 136 if _, err = syntax.ParseCID(record.ReplyTo.Cid); err != nil { 137 return nil, fmt.Errorf("invalid replyTo cid: %w", err) 138 } 139 } 140 141 var pullRoundIdx *int 142 if record.PullRoundIdx != nil { 143 pullRoundIdx = new(int) 144 *pullRoundIdx = int(*record.PullRoundIdx) 145 } 146 147 return &Comment{ 148 Did: did, 149 Collection: tangled.FeedCommentNSID, 150 Rkey: rkey, 151 Cid: cid, 152 153 Subject: *record.Subject, 154 Body: *record.Body.MarkupMarkdown, 155 Created: created, 156 ReplyTo: record.ReplyTo, 157 PullRoundIdx: pullRoundIdx, 158 }, nil 159}