From aa765ac3dd39f06b1e32bfe02fb6b5ca7e7b3a7e Mon Sep 17 00:00:00 2001 From: kolaente Date: Sat, 13 Feb 2021 21:34:16 +0100 Subject: [PATCH] Send notification to subscribers for task comment --- magefile.go | 2 +- pkg/models/listeners.go | 57 +++++++++++++++++++++++++++++++++++++ pkg/models/notifications.go | 29 +++++++++++++++++++ pkg/models/subscription.go | 29 +++++++++++++++++++ 4 files changed, 116 insertions(+), 1 deletion(-) diff --git a/magefile.go b/magefile.go index a4733b431..1aac4d31f 100644 --- a/magefile.go +++ b/magefile.go @@ -827,7 +827,7 @@ func (s *` + name + `) Name() string { return "` + listenerName + `" } -// Hanlde is executed when the event ` + name + ` listens on is fired +// Handle is executed when the event ` + name + ` listens on is fired func (s *` + name + `) Handle(payload message.Payload) (err error) { event := &` + event + `{} err = json.Unmarshal(payload, event) diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index 74826f76a..00241f652 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -17,9 +17,14 @@ package models import ( + "code.vikunja.io/api/pkg/db" "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/log" "code.vikunja.io/api/pkg/metrics" "code.vikunja.io/api/pkg/modules/keyvalue" + "code.vikunja.io/api/pkg/notifications" + "code.vikunja.io/api/pkg/user" + "encoding/json" "github.com/ThreeDotsLabs/watermill/message" ) @@ -33,6 +38,7 @@ func RegisterListeners() { events.RegisterListener((&TaskDeletedEvent{}).Name(), &DecreaseTaskCounter{}) events.RegisterListener((&TeamDeletedEvent{}).Name(), &DecreaseTeamCounter{}) events.RegisterListener((&TeamCreatedEvent{}).Name(), &IncreaseTeamCounter{}) + events.RegisterListener((&TaskCommentCreatedEvent{}).Name(), &SendTaskCommentNotification{}) } ////// @@ -66,6 +72,57 @@ func (s *DecreaseTaskCounter) Handle(payload message.Payload) (err error) { return keyvalue.DecrBy(metrics.TaskCountKey, 1) } +// SendTaskCommentNotification represents a listener +type SendTaskCommentNotification struct { +} + +// Name defines the name for the SendTaskCommentNotification listener +func (s *SendTaskCommentNotification) Name() string { + return "send.task.comment.notification" +} + +// Handle is executed when the event SendTaskCommentNotification listens on is fired +func (s *SendTaskCommentNotification) Handle(payload message.Payload) (err error) { + event := &TaskCommentCreatedEvent{} + err = json.Unmarshal(payload, event) + if err != nil { + return err + } + + doer, is := event.Doer.(*user.User) + if !is { + return + } + + sess := db.NewSession() + defer sess.Close() + + subscribers, err := getSubscribersForEntity(sess, SubscriptionEntityTask, event.Task.ID) + if err != nil { + return err + } + + log.Debugf("Sending task comment notifications to %d subscribers for task %d", len(subscribers), event.Task.ID) + + for _, subscriber := range subscribers { + if subscriber.UserID == doer.ID { + continue + } + + n := &TaskCommentNotification{ + Doer: doer, + Task: event.Task, + Comment: event.Comment, + } + err = notifications.Notify(subscriber.User, n) + if err != nil { + return + } + } + + return +} + /////// // List Event Listeners diff --git a/pkg/models/notifications.go b/pkg/models/notifications.go index af655aaae..10a06f1d0 100644 --- a/pkg/models/notifications.go +++ b/pkg/models/notifications.go @@ -17,7 +17,9 @@ package models import ( + "bufio" "strconv" + "strings" "code.vikunja.io/api/pkg/config" "code.vikunja.io/api/pkg/notifications" @@ -45,3 +47,30 @@ func (n *ReminderDueNotification) ToMail() *notifications.Mail { func (n *ReminderDueNotification) ToDB() interface{} { return nil } + +// TaskCommentNotification represents a TaskCommentNotification notification +type TaskCommentNotification struct { + Doer *user.User + Task *Task + Comment *TaskComment +} + +// ToMail returns the mail notification for TaskCommentNotification +func (n *TaskCommentNotification) ToMail() *notifications.Mail { + + mail := notifications.NewMail(). + Subject("Re: " + n.Task.Title) + + lines := bufio.NewScanner(strings.NewReader(n.Comment.Comment)) + for lines.Scan() { + mail.Line(lines.Text()) + } + + return mail. + Action("View Task", config.ServiceFrontendurl.GetString()+"tasks/"+strconv.FormatInt(n.Task.ID, 10)) +} + +// ToDB returns the TaskCommentNotification notification in a format which can be saved in the db +func (n *TaskCommentNotification) ToDB() interface{} { + return n +} diff --git a/pkg/models/subscription.go b/pkg/models/subscription.go index b20a3bc08..3a5807486 100644 --- a/pkg/models/subscription.go +++ b/pkg/models/subscription.go @@ -222,3 +222,32 @@ func GetSubscription(s *xorm.Session, entityType SubscriptionEntityType, entityI Get(subscription) return } + +func getSubscribersForEntity(s *xorm.Session, entityType SubscriptionEntityType, entityID int64) (subscriptions []*Subscription, err error) { + if err := entityType.validate(); err != nil { + return nil, err + } + + cond := getSubscriberCondForEntity(entityType, entityID) + err = s. + Where(cond). + Find(&subscriptions) + if err != nil { + return + } + + userIDs := []int64{} + for _, subscription := range subscriptions { + userIDs = append(userIDs, subscription.UserID) + } + + users, err := user.GetUsersByIDs(s, userIDs) + if err != nil { + return + } + + for _, subscription := range subscriptions { + subscription.User = users[subscription.UserID] + } + return +}