From c7b29fa19510daf4e766b689c7bc105742f35119 Mon Sep 17 00:00:00 2001 From: Mo Tarbin Date: Wed, 17 Jul 2024 01:09:47 -0400 Subject: [PATCH 1/2] Add CircleGroup notifications to chore notifications --- internal/chore/model/model.go | 10 +++--- internal/notifier/service/planner.go | 48 ++++++++++++++++++++++++++ internal/notifier/telegram/telegram.go | 31 +++++++++++++---- 3 files changed, 78 insertions(+), 11 deletions(-) diff --git a/internal/chore/model/model.go b/internal/chore/model/model.go index 3fb7a92..c9cf28c 100644 --- a/internal/chore/model/model.go +++ b/internal/chore/model/model.go @@ -51,10 +51,12 @@ type FrequencyMetadata struct { } type NotificationMetadata struct { - DueDate bool `json:"dueDate,omitempty"` - Completion bool `json:"completion,omitempty"` - Nagging bool `json:"nagging,omitempty"` - PreDue bool `json:"predue,omitempty"` + DueDate bool `json:"dueDate,omitempty"` + Completion bool `json:"completion,omitempty"` + Nagging bool `json:"nagging,omitempty"` + PreDue bool `json:"predue,omitempty"` + CircleGroup bool `json:"circleGroup,omitempty"` + CircleGroupID *int64 `json:"circleGroupID,omitempty"` } type Tag struct { diff --git a/internal/notifier/service/planner.go b/internal/notifier/service/planner.go index 05d600d..2f7f207 100644 --- a/internal/notifier/service/planner.go +++ b/internal/notifier/service/planner.go @@ -62,6 +62,9 @@ func (n *NotificationPlanner) GenerateNotifications(c context.Context, chore *ch if mt.Nagging { notifications = append(notifications, generateOverdueNotifications(chore, assignees)...) } + if mt.CircleGroup { + notifications = append(notifications, generateCircleGroupNotifications(chore, mt)...) + } n.nRepo.BatchInsertNotifications(notifications) return true @@ -150,3 +153,48 @@ func generateOverdueNotifications(chore *chModel.Chore, users []*cModel.UserCirc return notifications } + +func generateCircleGroupNotifications(chore *chModel.Chore, mt *chModel.NotificationMetadata) []*nModel.Notification { + var notifications []*nModel.Notification + if !mt.CircleGroup || mt.CircleGroupID == nil || *mt.CircleGroupID == 0 { + return notifications + } + if mt.DueDate { + notifications = append(notifications, &nModel.Notification{ + ChoreID: chore.ID, + IsSent: false, + ScheduledFor: *chore.NextDueDate, + CreatedAt: time.Now().UTC(), + TypeID: 1, + TargetID: fmt.Sprint(*mt.CircleGroupID), + Text: fmt.Sprintf("📅 Reminder: *%s* is due today.", chore.Name), + }) + } + if mt.PreDue { + notifications = append(notifications, &nModel.Notification{ + ChoreID: chore.ID, + IsSent: false, + ScheduledFor: *chore.NextDueDate, + CreatedAt: time.Now().UTC().Add(-time.Hour * 3), + 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")), + }) + } + if mt.Nagging { + for _, hours := range []int{24, 48, 72} { + scheduleTime := chore.NextDueDate.Add(time.Hour * time.Duration(hours)) + notifications = append(notifications, &nModel.Notification{ + ChoreID: chore.ID, + IsSent: false, + ScheduledFor: scheduleTime, + CreatedAt: time.Now().UTC(), + 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), + }) + } + } + + return notifications +} diff --git a/internal/notifier/telegram/telegram.go b/internal/notifier/telegram/telegram.go index 54c0905..3f064b6 100644 --- a/internal/notifier/telegram/telegram.go +++ b/internal/notifier/telegram/telegram.go @@ -2,6 +2,7 @@ package telegram import ( "context" + "encoding/json" "fmt" "strconv" @@ -49,22 +50,38 @@ func (tn *TelegramNotifier) SendChoreReminder(c context.Context, chore *chModel. } } -func (tn *TelegramNotifier) SendChoreCompletion(c context.Context, chore *chModel.Chore, users []*uModel.User) { +func (tn *TelegramNotifier) SendChoreCompletion(c context.Context, chore *chModel.Chore, user *uModel.User) { log := logging.FromContext(c) - for _, user := range users { - if user.ChatID == 0 { - continue + var mt *chModel.NotificationMetadata + if err := json.Unmarshal([]byte(*chore.NotificationMetadata), &mt); err != nil { + log.Error("Error unmarshalling notification metadata", err) + } + + targets := []int64{} + if user.ChatID != 0 { + targets = append(targets, user.ChatID) + } + if mt.CircleGroup && mt.CircleGroupID != nil { + // attempt to parse it: + + if *mt.CircleGroupID != 0 { + targets = append(targets, *mt.CircleGroupID) } - text := fmt.Sprintf("🎉 *%s* is completed! is off the list, %s! 🌟 ", chore.Name, user.DisplayName) - msg := tgbotapi.NewMessage(user.ChatID, text) + + } + + text := fmt.Sprintf("🎉 *%s* is completed! is off the list, %s! 🌟 ", chore.Name, user.DisplayName) + for _, target := range targets { + msg := tgbotapi.NewMessage(target, text) + msg.ParseMode = "Markdown" _, err := tn.bot.Send(msg) if err != nil { log.Error("Error sending message to user: ", err) log.Debug("Error sending message, chore: ", chore.Name, " user: ", user.DisplayName, " chatID: ", user.ChatID, " user id: ", user.ID) } - } + } func (tn *TelegramNotifier) SendChoreOverdue(c context.Context, chore *chModel.Chore, users []*uModel.User) { From 861a1666e48a91d43db6d1fd272dac832013f5b7 Mon Sep 17 00:00:00 2001 From: Mo Tarbin Date: Wed, 17 Jul 2024 01:11:20 -0400 Subject: [PATCH 2/2] Remove unnecessary code in skipChore and completeChore functions --- internal/chore/handler.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/internal/chore/handler.go b/internal/chore/handler.go index 5ec8cdd..0067940 100644 --- a/internal/chore/handler.go +++ b/internal/chore/handler.go @@ -683,12 +683,7 @@ func (h *Handler) skipChore(c *gin.Context) { }) return } - if err := h.choreRepo.UpsertChore(c, chore); err != nil { - c.JSON(500, gin.H{ - "error": "Error skipping chore", - }) - return - } + c.JSON(200, gin.H{ "res": chore, }) @@ -861,7 +856,7 @@ func (h *Handler) completeChore(c *gin.Context) { return } go func() { - h.notifier.SendChoreCompletion(c, chore, []*uModel.User{currentUser}) + h.notifier.SendChoreCompletion(c, chore, currentUser) h.nPlanner.GenerateNotifications(c, updatedChore) }() c.JSON(200, gin.H{