Signed-off-by: Seongmin Lee git@boltless.me
+11
-1
appview/notify/db/db.go
+11
-1
appview/notify/db/db.go
···
239
)
240
}
241
242
-
func (n *databaseNotifier) NewPullComment(ctx context.Context, comment *models.PullComment) {
243
pull, err := db.GetPull(n.db,
244
syntax.ATURI(comment.RepoAt),
245
comment.PullId,
···
283
issueId,
284
pullId,
285
)
286
}
287
288
func (n *databaseNotifier) UpdateProfile(ctx context.Context, profile *models.Profile) {
···
239
)
240
}
241
242
+
func (n *databaseNotifier) NewPullComment(ctx context.Context, comment *models.PullComment, mentions []syntax.DID) {
243
pull, err := db.GetPull(n.db,
244
syntax.ATURI(comment.RepoAt),
245
comment.PullId,
···
283
issueId,
284
pullId,
285
)
286
+
n.notifyEvent(
287
+
actorDid,
288
+
mentions,
289
+
models.NotificationTypeUserMentioned,
290
+
entityType,
291
+
entityId,
292
+
repoId,
293
+
issueId,
294
+
pullId,
295
+
)
296
}
297
298
func (n *databaseNotifier) UpdateProfile(ctx context.Context, profile *models.Profile) {
+2
-2
appview/notify/merged_notifier.go
+2
-2
appview/notify/merged_notifier.go
···
82
m.fanout("NewPull", ctx, pull)
83
}
84
85
+
func (m *mergedNotifier) NewPullComment(ctx context.Context, comment *models.PullComment, mentions []syntax.DID) {
86
+
m.fanout("NewPullComment", ctx, comment, mentions)
87
}
88
89
func (m *mergedNotifier) NewPullState(ctx context.Context, actor syntax.DID, pull *models.Pull) {
+4
-3
appview/notify/notifier.go
+4
-3
appview/notify/notifier.go
···
22
DeleteFollow(ctx context.Context, follow *models.Follow)
23
24
NewPull(ctx context.Context, pull *models.Pull)
25
-
NewPullComment(ctx context.Context, comment *models.PullComment)
26
NewPullState(ctx context.Context, actor syntax.DID, pull *models.Pull)
27
28
UpdateProfile(ctx context.Context, profile *models.Profile)
···
51
func (m *BaseNotifier) NewFollow(ctx context.Context, follow *models.Follow) {}
52
func (m *BaseNotifier) DeleteFollow(ctx context.Context, follow *models.Follow) {}
53
54
-
func (m *BaseNotifier) NewPull(ctx context.Context, pull *models.Pull) {}
55
-
func (m *BaseNotifier) NewPullComment(ctx context.Context, models *models.PullComment) {}
56
func (m *BaseNotifier) NewPullState(ctx context.Context, actor syntax.DID, pull *models.Pull) {}
57
58
func (m *BaseNotifier) UpdateProfile(ctx context.Context, profile *models.Profile) {}
···
22
DeleteFollow(ctx context.Context, follow *models.Follow)
23
24
NewPull(ctx context.Context, pull *models.Pull)
25
+
NewPullComment(ctx context.Context, comment *models.PullComment, mentions []syntax.DID)
26
NewPullState(ctx context.Context, actor syntax.DID, pull *models.Pull)
27
28
UpdateProfile(ctx context.Context, profile *models.Profile)
···
51
func (m *BaseNotifier) NewFollow(ctx context.Context, follow *models.Follow) {}
52
func (m *BaseNotifier) DeleteFollow(ctx context.Context, follow *models.Follow) {}
53
54
+
func (m *BaseNotifier) NewPull(ctx context.Context, pull *models.Pull) {}
55
+
func (m *BaseNotifier) NewPullComment(ctx context.Context, models *models.PullComment, mentions []syntax.DID) {
56
+
}
57
func (m *BaseNotifier) NewPullState(ctx context.Context, actor syntax.DID, pull *models.Pull) {}
58
59
func (m *BaseNotifier) UpdateProfile(ctx context.Context, profile *models.Profile) {}
+4
-3
appview/notify/posthog/notifier.go
+4
-3
appview/notify/posthog/notifier.go
···
86
}
87
}
88
89
-
func (n *posthogNotifier) NewPullComment(ctx context.Context, comment *models.PullComment) {
90
err := n.client.Enqueue(posthog.Capture{
91
DistinctId: comment.OwnerDid,
92
Event: "new_pull_comment",
93
Properties: posthog.Properties{
94
-
"repo_at": comment.RepoAt,
95
-
"pull_id": comment.PullId,
96
},
97
})
98
if err != nil {
···
86
}
87
}
88
89
+
func (n *posthogNotifier) NewPullComment(ctx context.Context, comment *models.PullComment, mentions []syntax.DID) {
90
err := n.client.Enqueue(posthog.Capture{
91
DistinctId: comment.OwnerDid,
92
Event: "new_pull_comment",
93
Properties: posthog.Properties{
94
+
"repo_at": comment.RepoAt,
95
+
"pull_id": comment.PullId,
96
+
"mentions": mentions,
97
},
98
})
99
if err != nil {
+3
-3
appview/pages/markup/extension/atlink.go
+3
-3
appview/pages/markup/extension/atlink.go
···
16
17
// An AtNode struct represents an AtNode
18
type AtNode struct {
19
-
handle string
20
ast.BaseInline
21
}
22
···
59
block.Advance(m[1])
60
node := &AtNode{}
61
node.AppendChild(node, ast.NewTextSegment(atSegment))
62
-
node.handle = string(atSegment.Value(block.Source())[1:])
63
return node
64
}
65
···
88
func (r *atHtmlRenderer) renderAt(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
89
if entering {
90
w.WriteString(`<a href="/@`)
91
-
w.WriteString(n.(*AtNode).handle)
92
w.WriteString(`" class="mention">`)
93
} else {
94
w.WriteString("</a>")
···
16
17
// An AtNode struct represents an AtNode
18
type AtNode struct {
19
+
Handle string
20
ast.BaseInline
21
}
22
···
59
block.Advance(m[1])
60
node := &AtNode{}
61
node.AppendChild(node, ast.NewTextSegment(atSegment))
62
+
node.Handle = string(atSegment.Value(block.Source())[1:])
63
return node
64
}
65
···
88
func (r *atHtmlRenderer) renderAt(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
89
if entering {
90
w.WriteString(`<a href="/@`)
91
+
w.WriteString(n.(*AtNode).Handle)
92
w.WriteString(`" class="mention">`)
93
} else {
94
w.WriteString("</a>")
+24
appview/pages/markup/markdown.go
+24
appview/pages/markup/markdown.go
···
302
return path.Join(rctx.CurrentDir, dst)
303
}
304
305
+
// FindUserMentions returns Set of user handles from given markup soruce.
306
+
// It doesn't guarntee unique DIDs
307
+
func FindUserMentions(source string) []string {
308
+
var (
309
+
mentions []string
310
+
mentionsSet = make(map[string]struct{})
311
+
md = NewMarkdown()
312
+
sourceBytes = []byte(source)
313
+
root = md.Parser().Parse(text.NewReader(sourceBytes))
314
+
)
315
+
ast.Walk(root, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
316
+
if entering && n.Kind() == textension.KindAt {
317
+
handle := n.(*textension.AtNode).Handle
318
+
mentionsSet[handle] = struct{}{}
319
+
return ast.WalkSkipChildren, nil
320
+
}
321
+
return ast.WalkContinue, nil
322
+
})
323
+
for handle := range mentionsSet {
324
+
mentions = append(mentions, handle)
325
+
}
326
+
return mentions
327
+
}
328
+
329
func isAbsoluteUrl(link string) bool {
330
parsed, err := url.Parse(link)
331
if err != nil {
+11
-1
appview/pulls/pulls.go
+11
-1
appview/pulls/pulls.go
···
691
}
692
693
func (s *Pulls) PullComment(w http.ResponseWriter, r *http.Request) {
694
user := s.oauth.GetUser(r)
695
f, err := s.repoResolver.Resolve(r)
696
if err != nil {
···
788
return
789
}
790
791
-
s.notifier.NewPullComment(r.Context(), comment)
792
793
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d#comment-%d", f.OwnerSlashRepo(), pull.PullId, commentId))
794
return
···
691
}
692
693
func (s *Pulls) PullComment(w http.ResponseWriter, r *http.Request) {
694
+
l := s.logger.With("handler", "PullComment")
695
user := s.oauth.GetUser(r)
696
f, err := s.repoResolver.Resolve(r)
697
if err != nil {
···
789
return
790
}
791
792
+
rawMentions := markup.FindUserMentions(comment.Body)
793
+
idents := s.idResolver.ResolveIdents(r.Context(), rawMentions)
794
+
l.Debug("parsed mentions", "raw", rawMentions, "idents", idents)
795
+
var mentions []syntax.DID
796
+
for _, ident := range idents {
797
+
if ident != nil && !ident.Handle.IsInvalidHandle() {
798
+
mentions = append(mentions, ident.DID)
799
+
}
800
+
}
801
+
s.notifier.NewPullComment(r.Context(), comment, mentions)
802
803
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d#comment-%d", f.OwnerSlashRepo(), pull.PullId, commentId))
804
return