From 29541ab42580504791b6f21917cd1723f264af89 Mon Sep 17 00:00:00 2001
From: William Perron <hey@wperron.io>
Date: Mon, 3 Mar 2025 14:27:27 -0500
Subject: [PATCH] Simplify time

---
 absences_test.go          |  4 ++--
 cmd/themis-server/main.go | 10 ++++++----
 notify.go                 |  6 +-----
 time.go                   | 21 +++------------------
 time_test.go              |  6 ++----
 5 files changed, 14 insertions(+), 33 deletions(-)

diff --git a/absences_test.go b/absences_test.go
index f6cc2c9..0ab496d 100644
--- a/absences_test.go
+++ b/absences_test.go
@@ -18,7 +18,7 @@ func TestAddAbsence(t *testing.T) {
 	store, err := NewStore(db, zerolog.Nop())
 	require.NoError(t, err)
 
-	now := NextOfWeekday(nil, ScheduledGameDay)
+	now := NextOfWeekday(ScheduledGameDay, time.Now())
 	assert.NoError(t, store.AddAbsence(context.TODO(), now, "foobarbaz"))
 	absentees, err := store.GetAbsentees(context.TODO(), now)
 	assert.NoError(t, err)
@@ -40,7 +40,7 @@ func TestGetSchedule(t *testing.T) {
 	store, err := NewStore(db, zerolog.Nop())
 	require.NoError(t, err)
 
-	now := NextOfWeekday(nil, ScheduledGameDay)
+	now := NextOfWeekday(ScheduledGameDay, time.Now())
 
 	_ = store.AddAbsence(context.TODO(), now.Add(7*24*time.Hour), "foobar")
 
diff --git a/cmd/themis-server/main.go b/cmd/themis-server/main.go
index ad7aa07..9c72186 100644
--- a/cmd/themis-server/main.go
+++ b/cmd/themis-server/main.go
@@ -501,6 +501,7 @@ func main() {
 			}
 			return nil
 		},
+		// flush is a special command that triggers a modal confirmation
 		"flush": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) error {
 			baggage := make(url.Values)
 			propagator.Inject(ctx, correlation.UrlValuesCarrier(baggage))
@@ -581,7 +582,7 @@ func main() {
 		},
 		"schedule": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) error {
 			// get schedule from now to 4 wednesdays into the future
-			sched, err := store.GetSchedule(ctx, themis.NextOfWeekday(nil, themis.ScheduledGameDay), themis.NextOfWeekday(nil, themis.ScheduledGameDay).Add(4*7*24*time.Hour))
+			sched, err := store.GetSchedule(ctx, themis.NextOfWeekday(themis.ScheduledGameDay, time.Now()), themis.NextOfWeekday(themis.ScheduledGameDay, time.Now()).Add(4*7*24*time.Hour))
 			if err != nil {
 				if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
 					Type: discordgo.InteractionResponseChannelMessageWithSource,
@@ -643,7 +644,7 @@ func main() {
 		"absent": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) error {
 			var rawDate string
 			if len(i.ApplicationCommandData().Options) == 0 {
-				rawDate = themis.NextOfWeekday(nil, themis.ScheduledGameDay).Format(time.DateOnly)
+				rawDate = themis.NextOfWeekday(themis.ScheduledGameDay, time.Now()).Format(time.DateOnly)
 			} else {
 				rawDate = i.ApplicationCommandData().Options[0].StringValue()
 			}
@@ -739,7 +740,7 @@ func main() {
 		defer span.End()
 
 		log.Info().Msg("sending weekly reminder")
-		absentees, err := store.GetAbsentees(ctx, themis.NextOfWeekday(nil, themis.ScheduledGameDay))
+		absentees, err := store.GetAbsentees(ctx, themis.NextOfWeekday(themis.ScheduledGameDay, time.Now()))
 		if err != nil {
 			log.Error().Err(err).Msg("failed to get absentees for next session")
 			return
@@ -806,6 +807,7 @@ func touchDbFile(path string) error {
 	return nil
 }
 
+// registerHandlers registers the handlers for the discord session
 func registerHandlers(sess *discordgo.Session, handlers map[string]Handler) {
 	sess.AddHandler(func(s *discordgo.Session, r *discordgo.Ready) {
 		log.Info().Str("user_id", fmt.Sprintf("%s#%s", s.State.User.Username, s.State.User.Discriminator)).Msg("logged in")
@@ -884,7 +886,7 @@ func registerHandlers(sess *discordgo.Session, handlers map[string]Handler) {
 				userId := i.Member.User.ID
 				log.Info().Ctx(ctx).Str("message_component", "schedule-response").Str("userid", userId).Msg("handling message component interaction")
 
-				if err := store.AddAbsence(ctx, themis.NextOfWeekday(nil, themis.ScheduledGameDay), userId); err != nil {
+				if err := store.AddAbsence(ctx, themis.NextOfWeekday(themis.ScheduledGameDay, time.Now()), userId); err != nil {
 					if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
 						Type: discordgo.InteractionResponseChannelMessageWithSource,
 						Data: &discordgo.InteractionResponseData{
diff --git a/notify.go b/notify.go
index accd5ee..8190aa0 100644
--- a/notify.go
+++ b/notify.go
@@ -26,11 +26,7 @@ func NewNotifier(c chan context.Context) *Notifier {
 }
 
 func (n *Notifier) Start(ctx context.Context) {
-	m := NextOfWeekday(nil, ScheduledGameDay)
-	sat := m.AddDate(0, 0, -4)
-	if sat.Before(time.Now()) {
-		sat = sat.AddDate(0, 0, 7)
-	}
+	sat := NextOfWeekday(time.Saturday, time.Now())
 
 	t, err := time.ParseInLocation(time.DateTime, fmt.Sprintf("%s 17:00:00", sat.Format(time.DateOnly)), onceLoc())
 	if err != nil {
diff --git a/time.go b/time.go
index 2e41398..1ba86cc 100644
--- a/time.go
+++ b/time.go
@@ -4,22 +4,7 @@ import "time"
 
 const ScheduledGameDay = time.Wednesday
 
-var defaultClock Clock = DefaultClock{}
-
-type Clock interface {
-	Now() time.Time
-}
-
-type DefaultClock struct{}
-
-func (DefaultClock) Now() time.Time {
-	return time.Now()
-}
-
-func NextOfWeekday(clock Clock, weekday time.Weekday) time.Time {
-	if clock == nil {
-		clock = defaultClock
-	}
-	now := clock.Now()
-	return now.AddDate(0, 0, int(((7+weekday)-now.Weekday())%7))
+func NextOfWeekday(weekday time.Weekday, from time.Time) time.Time {
+	diff := (7 + int(weekday-from.Weekday())) % 7
+	return from.AddDate(0, 0, diff)
 }
diff --git a/time_test.go b/time_test.go
index e18f040..6111eff 100644
--- a/time_test.go
+++ b/time_test.go
@@ -51,8 +51,7 @@ func TestNextWednesday(t *testing.T) {
 			wantt, err := time.Parse(time.RFC3339, tt.want)
 			require.NoError(t, err)
 
-			testClock := TestClock{now: seedt}
-			if got := NextOfWeekday(testClock, time.Wednesday); !reflect.DeepEqual(got, wantt) {
+			if got := NextOfWeekday(time.Wednesday, seedt); !reflect.DeepEqual(got, wantt) {
 				t.Errorf("NextWednesday() = %v, want %v", got, wantt)
 			}
 		})
@@ -94,8 +93,7 @@ func TestNextMonday(t *testing.T) {
 			wantt, err := time.Parse(time.RFC3339, tt.want)
 			require.NoError(t, err)
 
-			testClock := TestClock{now: seedt}
-			if got := NextOfWeekday(testClock, time.Monday); !reflect.DeepEqual(got, wantt) {
+			if got := NextOfWeekday(time.Monday, seedt); !reflect.DeepEqual(got, wantt) {
 				t.Errorf("NextWednesday() = %v, want %v", got, wantt)
 			}
 		})