Monorepo for Tangled tangled.org
at sl/shared-stacks 138 lines 3.4 kB view raw
1package models 2 3import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "github.com/bluesky-social/indigo/atproto/syntax" 9 "github.com/whyrusleeping/cbor-gen" 10 "tangled.org/core/api/tangled" 11) 12 13type Comment struct { 14 Id int64 15 Did syntax.DID 16 Collection syntax.NSID 17 Rkey string 18 Subject syntax.ATURI 19 ReplyTo *syntax.ATURI 20 Body string 21 Created time.Time 22 Edited *time.Time 23 Deleted *time.Time 24 Mentions []syntax.DID 25 References []syntax.ATURI 26 PullSubmissionId *int 27} 28 29func (c *Comment) AtUri() syntax.ATURI { 30 return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", c.Did, c.Collection, c.Rkey)) 31} 32 33func (c *Comment) AsRecord() typegen.CBORMarshaler { 34 mentions := make([]string, len(c.Mentions)) 35 for i, did := range c.Mentions { 36 mentions[i] = string(did) 37 } 38 references := make([]string, len(c.References)) 39 for i, uri := range c.References { 40 references[i] = string(uri) 41 } 42 var replyTo *string 43 if c.ReplyTo != nil { 44 replyToStr := c.ReplyTo.String() 45 replyTo = &replyToStr 46 } 47 switch c.Collection { 48 case tangled.RepoIssueCommentNSID: 49 return &tangled.RepoIssueComment{ 50 Issue: c.Subject.String(), 51 Body: c.Body, 52 CreatedAt: c.Created.Format(time.RFC3339), 53 ReplyTo: replyTo, 54 Mentions: mentions, 55 References: references, 56 } 57 case tangled.RepoPullCommentNSID: 58 return &tangled.RepoPullComment{ 59 Pull: c.Subject.String(), 60 Body: c.Body, 61 CreatedAt: c.Created.Format(time.RFC3339), 62 Mentions: mentions, 63 References: references, 64 } 65 default: // default to CommentNSID 66 return &tangled.Comment{ 67 Subject: c.Subject.String(), 68 Body: c.Body, 69 CreatedAt: c.Created.Format(time.RFC3339), 70 ReplyTo: replyTo, 71 Mentions: mentions, 72 References: references, 73 } 74 } 75} 76 77func (c *Comment) IsTopLevel() bool { 78 return c.ReplyTo == nil 79} 80 81func (c *Comment) IsReply() bool { 82 return c.ReplyTo != nil 83} 84 85func (c *Comment) Validate() error { 86 // TODO: sanitize the body and then trim space 87 if sb := strings.TrimSpace(c.Body); sb == "" { 88 return fmt.Errorf("body is empty after HTML sanitization") 89 } 90 91 // if it's for PR, PullSubmissionId should not be nil 92 if c.Subject.Collection().String() == tangled.RepoPullNSID { 93 if c.PullSubmissionId == nil { 94 return fmt.Errorf("PullSubmissionId should not be nil") 95 } 96 } 97 return nil 98} 99 100func CommentFromRecord(did syntax.DID, rkey syntax.RecordKey, record tangled.Comment) (*Comment, error) { 101 created, err := time.Parse(time.RFC3339, record.CreatedAt) 102 if err != nil { 103 created = time.Now() 104 } 105 106 if _, err = syntax.ParseATURI(record.Subject); err != nil { 107 return nil, err 108 } 109 110 i := record 111 mentions := make([]syntax.DID, len(record.Mentions)) 112 for i, did := range record.Mentions { 113 mentions[i] = syntax.DID(did) 114 } 115 references := make([]syntax.ATURI, len(record.References)) 116 for i, uri := range i.References { 117 references[i] = syntax.ATURI(uri) 118 } 119 var replyTo *syntax.ATURI 120 if record.ReplyTo != nil { 121 replyToAtUri := syntax.ATURI(*record.ReplyTo) 122 replyTo = &replyToAtUri 123 } 124 125 comment := Comment{ 126 Did: did, 127 Collection: tangled.CommentNSID, 128 Rkey: rkey.String(), 129 Body: record.Body, 130 Subject: syntax.ATURI(record.Subject), 131 ReplyTo: replyTo, 132 Created: created, 133 Mentions: mentions, 134 References: references, 135 } 136 137 return &comment, nil 138}