forked from tangled.org/core
Monorepo for Tangled — https://tangled.org

appview/notify: notify users mentioned on PR comments

Signed-off-by: Seongmin Lee <git@boltless.me>

authored by boltless.me and committed by Tangled 10ad3506 b02199b3

Changed files
+35 -13
appview
notify
pages
markup
extension
pulls
+11 -1
appview/notify/db/db.go
··· 239 239 ) 240 240 } 241 241 242 - func (n *databaseNotifier) NewPullComment(ctx context.Context, comment *models.PullComment) { 242 + func (n *databaseNotifier) NewPullComment(ctx context.Context, comment *models.PullComment, mentions []syntax.DID) { 243 243 pull, err := db.GetPull(n.db, 244 244 syntax.ATURI(comment.RepoAt), 245 245 comment.PullId, ··· 277 277 actorDid, 278 278 recipients, 279 279 eventType, 280 + entityType, 281 + entityId, 282 + repoId, 283 + issueId, 284 + pullId, 285 + ) 286 + n.notifyEvent( 287 + actorDid, 288 + mentions, 289 + models.NotificationTypeUserMentioned, 280 290 entityType, 281 291 entityId, 282 292 repoId,
+2 -2
appview/notify/merged_notifier.go
··· 82 82 m.fanout("NewPull", ctx, pull) 83 83 } 84 84 85 - func (m *mergedNotifier) NewPullComment(ctx context.Context, comment *models.PullComment) { 86 - m.fanout("NewPullComment", ctx, comment) 85 + func (m *mergedNotifier) NewPullComment(ctx context.Context, comment *models.PullComment, mentions []syntax.DID) { 86 + m.fanout("NewPullComment", ctx, comment, mentions) 87 87 } 88 88 89 89 func (m *mergedNotifier) NewPullState(ctx context.Context, actor syntax.DID, pull *models.Pull) {
+4 -3
appview/notify/notifier.go
··· 22 22 DeleteFollow(ctx context.Context, follow *models.Follow) 23 23 24 24 NewPull(ctx context.Context, pull *models.Pull) 25 - NewPullComment(ctx context.Context, comment *models.PullComment) 25 + NewPullComment(ctx context.Context, comment *models.PullComment, mentions []syntax.DID) 26 26 NewPullState(ctx context.Context, actor syntax.DID, pull *models.Pull) 27 27 28 28 UpdateProfile(ctx context.Context, profile *models.Profile) ··· 51 51 func (m *BaseNotifier) NewFollow(ctx context.Context, follow *models.Follow) {} 52 52 func (m *BaseNotifier) DeleteFollow(ctx context.Context, follow *models.Follow) {} 53 53 54 - func (m *BaseNotifier) NewPull(ctx context.Context, pull *models.Pull) {} 55 - func (m *BaseNotifier) NewPullComment(ctx context.Context, models *models.PullComment) {} 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 + } 56 57 func (m *BaseNotifier) NewPullState(ctx context.Context, actor syntax.DID, pull *models.Pull) {} 57 58 58 59 func (m *BaseNotifier) UpdateProfile(ctx context.Context, profile *models.Profile) {}
+4 -3
appview/notify/posthog/notifier.go
··· 86 86 } 87 87 } 88 88 89 - func (n *posthogNotifier) NewPullComment(ctx context.Context, comment *models.PullComment) { 89 + func (n *posthogNotifier) NewPullComment(ctx context.Context, comment *models.PullComment, mentions []syntax.DID) { 90 90 err := n.client.Enqueue(posthog.Capture{ 91 91 DistinctId: comment.OwnerDid, 92 92 Event: "new_pull_comment", 93 93 Properties: posthog.Properties{ 94 - "repo_at": comment.RepoAt, 95 - "pull_id": comment.PullId, 94 + "repo_at": comment.RepoAt, 95 + "pull_id": comment.PullId, 96 + "mentions": mentions, 96 97 }, 97 98 }) 98 99 if err != nil {
+3 -3
appview/pages/markup/extension/atlink.go
··· 16 16 17 17 // An AtNode struct represents an AtNode 18 18 type AtNode struct { 19 - handle string 19 + Handle string 20 20 ast.BaseInline 21 21 } 22 22 ··· 59 59 block.Advance(m[1]) 60 60 node := &AtNode{} 61 61 node.AppendChild(node, ast.NewTextSegment(atSegment)) 62 - node.handle = string(atSegment.Value(block.Source())[1:]) 62 + node.Handle = string(atSegment.Value(block.Source())[1:]) 63 63 return node 64 64 } 65 65 ··· 88 88 func (r *atHtmlRenderer) renderAt(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) { 89 89 if entering { 90 90 w.WriteString(`<a href="/@`) 91 - w.WriteString(n.(*AtNode).handle) 91 + w.WriteString(n.(*AtNode).Handle) 92 92 w.WriteString(`" class="mention">`) 93 93 } else { 94 94 w.WriteString("</a>")
+11 -1
appview/pulls/pulls.go
··· 691 691 } 692 692 693 693 func (s *Pulls) PullComment(w http.ResponseWriter, r *http.Request) { 694 + l := s.logger.With("handler", "PullComment") 694 695 user := s.oauth.GetUser(r) 695 696 f, err := s.repoResolver.Resolve(r) 696 697 if err != nil { ··· 788 789 return 789 790 } 790 791 791 - s.notifier.NewPullComment(r.Context(), comment) 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) 792 802 793 803 s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d#comment-%d", f.OwnerSlashRepo(), pull.PullId, commentId)) 794 804 return