Add Event Producer

Update User to carry webhook from circle if assigned
Refactor notification handling and update models for webhook support
This commit is contained in:
Mo Tarbin 2025-02-09 20:15:28 -05:00
parent 44cb5501dd
commit 04d1894aea
17 changed files with 351 additions and 101 deletions

View file

@ -65,7 +65,7 @@ func (n *NotificationPlanner) GenerateNotifications(c context.Context, chore *ch
if mt.CircleGroup {
notifications = append(notifications, generateCircleGroupNotifications(chore, mt)...)
}
log.Debug("Generated notifications", "count", len(notifications))
n.nRepo.BatchInsertNotifications(notifications)
return true
}
@ -89,6 +89,13 @@ func generateDueNotifications(chore *chModel.Chore, users []*cModel.UserCircleDe
UserID: user.ID,
TargetID: user.TargetID,
Text: fmt.Sprintf("📅 Reminder: *%s* is due today and assigned to %s.", chore.Name, assignee.DisplayName),
RawEvent: map[string]interface{}{
"id": chore.ID,
"name": chore.Name,
"due_date": chore.NextDueDate.Format("January 2nd"),
"assignee": assignee.DisplayName,
"assignee_username": assignee.Username,
},
}
if notification.IsValid() {
notifications = append(notifications, notification)
@ -117,6 +124,13 @@ func generatePreDueNotifications(chore *chModel.Chore, users []*cModel.UserCircl
UserID: user.ID,
TargetID: user.TargetID,
Text: fmt.Sprintf("📢 Heads up! *%s* is due soon (on %s) and assigned to %s.", chore.Name, chore.NextDueDate.Format("January 2nd"), assignee.DisplayName),
RawEvent: map[string]interface{}{
"id": chore.ID,
"name": chore.Name,
"due_date": chore.NextDueDate.Format("January 2nd"),
"assignee": assignee.DisplayName,
"assignee_username": assignee.Username,
},
}
if notification.IsValid() {
notifications = append(notifications, notification)
@ -148,6 +162,14 @@ func generateOverdueNotifications(chore *chModel.Chore, users []*cModel.UserCirc
UserID: user.ID,
TargetID: fmt.Sprint(user.TargetID),
Text: fmt.Sprintf("🚨 *%s* is now %d hours overdue. Please complete it as soon as possible. (Assigned to %s)", chore.Name, hours, assignee.DisplayName),
RawEvent: map[string]interface{}{
"id": chore.ID,
"type": EventTypeOverdue,
"name": chore.Name,
"due_date": chore.NextDueDate.Format("January 2nd"),
"assignee": assignee.DisplayName,
"assignee_username": assignee.Username,
},
}
if notification.IsValid() {
notifications = append(notifications, notification)
@ -173,6 +195,12 @@ func generateCircleGroupNotifications(chore *chModel.Chore, mt *chModel.Notifica
TypeID: 1,
TargetID: fmt.Sprint(*mt.CircleGroupID),
Text: fmt.Sprintf("📅 Reminder: *%s* is due today.", chore.Name),
RawEvent: map[string]interface{}{
"id": chore.ID,
"type": EventTypeDue,
"name": chore.Name,
"due_date": chore.NextDueDate.Format("January 2nd"),
},
}
if notification.IsValid() {
notifications = append(notifications, notification)
@ -188,6 +216,12 @@ func generateCircleGroupNotifications(chore *chModel.Chore, mt *chModel.Notifica
TypeID: 3,
TargetID: fmt.Sprint(*mt.CircleGroupID),
Text: fmt.Sprintf("📢 Heads up! *%s* is due soon (on %s).", chore.Name, chore.NextDueDate.Format("January 2nd")),
RawEvent: map[string]interface{}{
"id": chore.ID,
"type": EventTypePreDue,
"name": chore.Name,
"due_date": chore.NextDueDate.Format("January 2nd"),
},
}
if notification.IsValid() {
notifications = append(notifications, notification)
@ -205,6 +239,12 @@ func generateCircleGroupNotifications(chore *chModel.Chore, mt *chModel.Notifica
TypeID: 2,
TargetID: fmt.Sprint(*mt.CircleGroupID),
Text: fmt.Sprintf("🚨 *%s* is now %d hours overdue. Please complete it as soon as possible.", chore.Name, hours),
RawEvent: map[string]interface{}{
"id": chore.ID,
"type": EventTypeOverdue,
"name": chore.Name,
"due_date": chore.NextDueDate.Format("January 2nd"),
},
}
if notification.IsValid() {
notifications = append(notifications, notification)
@ -214,3 +254,12 @@ func generateCircleGroupNotifications(chore *chModel.Chore, mt *chModel.Notifica
return notifications
}
type EventType string
const (
EventTypeUnknown EventType = "unknown"
EventTypeDue EventType = "due"
EventTypePreDue EventType = "pre_due"
EventTypeOverdue EventType = "overdue"
)

View file

@ -2,6 +2,7 @@ package pushover
import (
"context"
"errors"
"donetick.com/core/config"
nModel "donetick.com/core/internal/notifier/model"
@ -22,7 +23,10 @@ func NewPushover(cfg *config.Config) *Pushover {
}
}
func (p *Pushover) SendNotification(c context.Context, notification *nModel.Notification) error {
func (p *Pushover) SendNotification(c context.Context, notification *nModel.NotificationDetails) error {
if notification.TargetID == "" {
return errors.New("unable to send notification, targetID is empty")
}
log := logging.FromContext(c)
recipient := pushover.NewRecipient(notification.TargetID)
message := pushover.NewMessageWithTitle(notification.Text, "Donetick")

View file

@ -70,12 +70,10 @@ func (tn *TelegramNotifier) SendChoreCompletion(c context.Context, chore *chMode
}
func (tn *TelegramNotifier) SendNotification(c context.Context, notification *nModel.Notification) error {
func (tn *TelegramNotifier) SendNotification(c context.Context, notification *nModel.NotificationDetails) error {
log := logging.FromContext(c)
if notification.TargetID == "" {
log.Error("Notification target ID is empty")
return errors.New("Notification target ID is empty")
return errors.New("unable to send notification, targetID is empty")
}
chatID, err := strconv.ParseInt(notification.TargetID, 10, 64)
if err != nil {