feat: add eve chanting notif
This commit is contained in:
@@ -15,6 +15,7 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -37,6 +38,10 @@ const (
|
||||
// the overlap.
|
||||
reminderWindowMin = 20
|
||||
|
||||
// The evening "finish your rounds" reminder fires at 21:00 local. Kept
|
||||
// before the 21:30 quote reminder so the two don't collide in one tick.
|
||||
chantIncompleteTime = "21:00"
|
||||
|
||||
chantMsgStart = "Chant with Prabhupāda — start building your sādhana streak."
|
||||
chantMsgLapsed = "Just one hour of sādhana can save you from this duḥkhālayam aśāśvatam. Come and build your streak again."
|
||||
chantMsgYesterday = "Your sādhana was wonderful yesterday! Let's continue your sādhana today as well."
|
||||
@@ -112,6 +117,21 @@ func (s *ReminderService) RunOnce(ctx context.Context, now time.Time) {
|
||||
}
|
||||
}
|
||||
|
||||
// Evening "incomplete chanting" reminder — the devotee started their
|
||||
// rounds today (RoundsToday > 0) but hasn't reached the target by
|
||||
// 21:00 local. Only nudges those who began, so non-starters get just
|
||||
// the morning reminder, not a second one. Independent of the morning
|
||||
// chant reminder (own time + own per-day dedupe).
|
||||
if c.RoundsToday > 0 && !c.ChantDoneToday && notRemindedToday(c.LastChantIncompleteOn, utcToday) {
|
||||
if t := parseHHMM(chantIncompleteTime); t >= 0 && withinWindow(localMin, t) {
|
||||
s.notif.SendReminder(ctx, c.UserID, NotifChantIncomplete,
|
||||
"Finish your japa 🙏", incompleteChantMessage(c.RoundsToday, c.TargetRounds), s.sadhnaURL)
|
||||
if err := s.repo.MarkChantIncompleteReminded(ctx, c.UserID, utcToday); err != nil {
|
||||
s.logger.Warn("reminders: mark chant-incomplete failed", zap.String("user", c.UserID), zap.Error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Quote reminder.
|
||||
if !c.QuoteDoneToday && notRemindedToday(c.LastQuoteOn, utcToday) {
|
||||
if t := parseHHMM(c.QuoteTime); t >= 0 && withinWindow(localMin, t) {
|
||||
@@ -143,6 +163,17 @@ func chantMessage(lastChant *time.Time, utcToday time.Time) string {
|
||||
}
|
||||
}
|
||||
|
||||
// incompleteChantMessage nudges a devotee who began their rounds today to
|
||||
// finish them (only sent when rounds > 0).
|
||||
func incompleteChantMessage(rounds, target int) string {
|
||||
if target <= 0 {
|
||||
target = 16
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
"You've chanted %d of %d rounds today — finish your japa before the day ends. 🙏",
|
||||
rounds, target)
|
||||
}
|
||||
|
||||
// notRemindedToday is true when no reminder of this kind has gone out on the
|
||||
// current UTC day.
|
||||
func notRemindedToday(last *time.Time, utcToday time.Time) bool {
|
||||
|
||||
Reference in New Issue
Block a user