···1+package models
2+3+import (
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+13+type 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+29+func (c *Comment) AtUri() syntax.ATURI {
30+ return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", c.Did, c.Collection, c.Rkey))
31+}
32+33+func (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+77+func (c *Comment) IsTopLevel() bool {
78+ return c.ReplyTo == nil
79+}
80+81+func (c *Comment) IsReply() bool {
82+ return c.ReplyTo != nil
83+}
84+85+func (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+100+func 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+}
+2-28
appview/models/pull.go
···138 RoundNumber int
139 Patch string
140 Combined string
141- Comments []PullComment
142 SourceRev string // include the rev that was used to create this submission: only for branch/fork PRs
143144 // meta
145 Created time.Time
146-}
147-148-type PullComment struct {
149- // ids
150- ID int
151- PullId int
152- SubmissionId int
153-154- // at ids
155- RepoAt string
156- OwnerDid string
157- CommentAt string
158-159- // content
160- Body string
161-162- // meta
163- Mentions []syntax.DID
164- References []syntax.ATURI
165-166- // meta
167- Created time.Time
168-}
169-170-func (p *PullComment) AtUri() syntax.ATURI {
171- return syntax.ATURI(p.CommentAt)
172}
173174func (p *Pull) TotalComments() int {
···279 addParticipant(s.PullAt.Authority().String())
280281 for _, c := range s.Comments {
282- addParticipant(c.OwnerDid)
283 }
284285 return participants
···138 RoundNumber int
139 Patch string
140 Combined string
141+ Comments []Comment
142 SourceRev string // include the rev that was used to create this submission: only for branch/fork PRs
143144 // meta
145 Created time.Time
00000000000000000000000000146}
147148func (p *Pull) TotalComments() int {
···253 addParticipant(s.PullAt.Authority().String())
254255 for _, c := range s.Comments {
256+ addParticipant(c.Did.String())
257 }
258259 return participants