Add mention notifications for new and updated descriptions

This commit is contained in:
kolaente 2021-07-29 16:36:01 +02:00
parent 347700936f
commit b49d223f68
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
3 changed files with 130 additions and 16 deletions

View File

@ -47,6 +47,8 @@ func RegisterListeners() {
events.RegisterListener((&TaskAssigneeCreatedEvent{}).Name(), &SubscribeAssigneeToTask{})
events.RegisterListener((&TeamMemberAddedEvent{}).Name(), &SendTeamMemberAddedNotification{})
events.RegisterListener((&TaskCommentUpdatedEvent{}).Name(), &HandleTaskCommentEditMentions{})
events.RegisterListener((&TaskCreatedEvent{}).Name(), &HandleTaskCreateMentions{})
events.RegisterListener((&TaskUpdatedEvent{}).Name(), &HandleTaskUpdatedMentions{})
}
//////
@ -61,7 +63,7 @@ func (s *IncreaseTaskCounter) Name() string {
return "task.counter.increase"
}
// Hanlde is executed when the event IncreaseTaskCounter listens on is fired
// Handle is executed when the event IncreaseTaskCounter listens on is fired
func (s *IncreaseTaskCounter) Handle(msg *message.Message) (err error) {
return keyvalue.IncrBy(metrics.TaskCountKey, 1)
}
@ -75,13 +77,13 @@ func (s *DecreaseTaskCounter) Name() string {
return "task.counter.decrease"
}
// Hanlde is executed when the event DecreaseTaskCounter listens on is fired
// Handle is executed when the event DecreaseTaskCounter listens on is fired
func (s *DecreaseTaskCounter) Handle(msg *message.Message) (err error) {
return keyvalue.DecrBy(metrics.TaskCountKey, 1)
}
func notifyMentionedUsers(sess *xorm.Session, task *Task, comment *TaskComment, doer *user.User) (users map[int64]*user.User, err error) {
users, err = FindMentionedUsersInText(sess, comment.Comment)
func notifyMentionedUsers(sess *xorm.Session, task *Task, text string, n notifications.NotificationWithSubject) (users map[int64]*user.User, err error) {
users, err = FindMentionedUsersInText(sess, text)
if err != nil {
return
}
@ -90,7 +92,7 @@ func notifyMentionedUsers(sess *xorm.Session, task *Task, comment *TaskComment,
return
}
log.Debugf("Processing %d mentioned users for comment %d", len(users), comment.ID)
log.Debugf("Processing %d mentioned users for text %d", len(users), n.SubjectID())
var notified int
outer:
@ -105,7 +107,7 @@ outer:
}
// Don't notify a user if they were already notified
dbn, err := notifications.GetNotificationsForEventAndUser(sess, u.ID, (&TaskCommentNotification{}).Name(), comment.ID)
dbn, err := notifications.GetNotificationsForEventAndUser(sess, u.ID, n.Name(), n.SubjectID())
if err != nil {
return users, err
}
@ -114,12 +116,6 @@ outer:
continue outer
}
n := &TaskCommentNotification{
Doer: doer,
Task: task,
Comment: comment,
Mentioned: true,
}
err = notifications.Notify(u, n)
if err != nil {
return users, err
@ -127,7 +123,7 @@ outer:
notified++
}
log.Debugf("Notified %d mentioned users for comment %d", notified, comment.ID)
log.Debugf("Notified %d mentioned users for text %d", notified, n.SubjectID())
return
}
@ -152,7 +148,13 @@ func (s *SendTaskCommentNotification) Handle(msg *message.Message) (err error) {
sess := db.NewSession()
defer sess.Close()
mentionedUsers, err := notifyMentionedUsers(sess, event.Task, event.Comment, event.Doer)
n := &TaskCommentNotification{
Doer: event.Doer,
Task: event.Task,
Comment: event.Comment,
Mentioned: true,
}
mentionedUsers, err := notifyMentionedUsers(sess, event.Task, event.Comment.Comment, n)
if err != nil {
return err
}
@ -207,7 +209,13 @@ func (s *HandleTaskCommentEditMentions) Handle(msg *message.Message) (err error)
sess := db.NewSession()
defer sess.Close()
_, err = notifyMentionedUsers(sess, event.Task, event.Comment, event.Doer)
n := &TaskCommentNotification{
Doer: event.Doer,
Task: event.Task,
Comment: event.Comment,
Mentioned: true,
}
_, err = notifyMentionedUsers(sess, event.Task, event.Comment.Comment, n)
return err
}
@ -335,6 +343,65 @@ func (s *SubscribeAssigneeToTask) Handle(msg *message.Message) (err error) {
return sess.Commit()
}
// HandleTaskCreateMentions represents a listener
type HandleTaskCreateMentions struct {
}
// Name defines the name for the HandleTaskCreateMentions listener
func (s *HandleTaskCreateMentions) Name() string {
return "task.created.mentions"
}
// Handle is executed when the event HandleTaskCreateMentions listens on is fired
func (s *HandleTaskCreateMentions) Handle(msg *message.Message) (err error) {
event := &TaskCreatedEvent{}
err = json.Unmarshal(msg.Payload, event)
if err != nil {
return err
}
sess := db.NewSession()
defer sess.Close()
n := &UserMentionedInTaskNotification{
Task: event.Task,
Doer: event.Doer,
IsNew: true,
}
_, err = notifyMentionedUsers(sess, event.Task, event.Task.Description, n)
return err
}
// HandleTaskUpdatedMentions represents a listener
type HandleTaskUpdatedMentions struct {
}
// Name defines the name for the HandleTaskUpdatedMentions listener
func (s *HandleTaskUpdatedMentions) Name() string {
return "task.updated.mentions"
}
// Handle is executed when the event HandleTaskUpdatedMentions listens on is fired
func (s *HandleTaskUpdatedMentions) Handle(msg *message.Message) (err error) {
event := &TaskUpdatedEvent{}
err = json.Unmarshal(msg.Payload, event)
if err != nil {
return err
}
sess := db.NewSession()
defer sess.Close()
n := &UserMentionedInTaskNotification{
Task: event.Task,
Doer: event.Doer,
IsNew: false,
}
_, err = notifyMentionedUsers(sess, event.Task, event.Task.Description, n)
return err
}
///////
// List Event Listeners

View File

@ -76,7 +76,7 @@ func (n *TaskCommentNotification) ToMail() *notifications.Mail {
subject := "Re: " + n.Task.Title
if n.Mentioned {
subject = n.Doer.GetName() + " mentioned you in a comment at " + n.Task.Title
subject = n.Doer.GetName() + ` mentioned you in a comment in "` + n.Task.Title + `"`
mail.Line(n.Doer.GetName() + " mentioned you in a comment:")
}
@ -260,3 +260,45 @@ func (n *UndoneTasksOverdueNotification) ToDB() interface{} {
func (n *UndoneTasksOverdueNotification) Name() string {
return "task.undone.overdue"
}
// UserMentionedInTaskNotification represents a UserMentionedInTaskNotification notification
type UserMentionedInTaskNotification struct {
Doer *user.User `json:"doer"`
Task *Task `json:"task"`
IsNew bool `json:"is_new"`
}
func (n *UserMentionedInTaskNotification) SubjectID() int64 {
return n.Task.ID
}
// ToMail returns the mail notification for UserMentionedInTaskNotification
func (n *UserMentionedInTaskNotification) ToMail() *notifications.Mail {
subject := n.Doer.GetName() + ` mentioned you in a new task "` + n.Task.Title + `"`
if n.IsNew {
subject = n.Doer.GetName() + ` mentioned you in a task "` + n.Task.Title + `"`
}
mail := notifications.NewMail().
From(n.Doer.GetNameAndFromEmail()).
Subject(subject).
Line(n.Doer.GetName() + " mentioned you in a task:")
lines := bufio.NewScanner(strings.NewReader(n.Task.Description))
for lines.Scan() {
mail.Line(lines.Text())
}
return mail.
Action("View Task", n.Task.GetFrontendURL())
}
// ToDB returns the UserMentionedInTaskNotification notification in a format which can be saved in the db
func (n *UserMentionedInTaskNotification) ToDB() interface{} {
return n
}
// Name returns the name of the notification
func (n *UserMentionedInTaskNotification) Name() string {
return "task.mentioned"
}

View File

@ -33,6 +33,11 @@ type SubjectID interface {
SubjectID() int64
}
type NotificationWithSubject interface {
Notification
SubjectID
}
// Notifiable is an entity which can be notified. Usually a user.
type Notifiable interface {
// Should return the email address this notifiable has.