Compare commits

...

2 Commits

@ -22,10 +22,10 @@ func (s *Store) AddAbsence(ctx context.Context, session time.Time, userId string
)) ))
defer span.End() defer span.End()
if session.Weekday() != time.Monday { if session.Weekday() != time.Wednesday {
log.Debug().Ctx(ctx).Msg(fmt.Sprintf("%s is not a monday", session)) log.Debug().Ctx(ctx).Msg(fmt.Sprintf("%s is not a wednesday", session))
span.RecordError(fmt.Errorf("%s is not a monday", session)) span.RecordError(fmt.Errorf("%s is not a wednesday", session))
return fmt.Errorf("not a monday") return fmt.Errorf("not a wednesday")
} }
defer s.Audit(ctx, &AuditableEvent{ defer s.Audit(ctx, &AuditableEvent{

@ -18,7 +18,7 @@ func TestAddAbsence(t *testing.T) {
store, err := NewStore(db, zerolog.Nop()) store, err := NewStore(db, zerolog.Nop())
require.NoError(t, err) require.NoError(t, err)
now := NextWednesday() now := NextWednesday(nil)
assert.NoError(t, store.AddAbsence(context.TODO(), now, "foobarbaz")) assert.NoError(t, store.AddAbsence(context.TODO(), now, "foobarbaz"))
absentees, err := store.GetAbsentees(context.TODO(), now) absentees, err := store.GetAbsentees(context.TODO(), now)
assert.NoError(t, err) assert.NoError(t, err)
@ -40,7 +40,7 @@ func TestGetSchedule(t *testing.T) {
store, err := NewStore(db, zerolog.Nop()) store, err := NewStore(db, zerolog.Nop())
require.NoError(t, err) require.NoError(t, err)
now := NextWednesday() now := NextWednesday(nil)
_ = store.AddAbsence(context.TODO(), now.Add(7*24*time.Hour), "foobar") _ = store.AddAbsence(context.TODO(), now.Add(7*24*time.Hour), "foobar")

@ -580,8 +580,8 @@ func main() {
return nil return nil
}, },
"schedule": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) error { "schedule": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) error {
// get schedule from now to 4 mondays into the future // get schedule from now to 4 wednesdays into the future
sched, err := store.GetSchedule(ctx, themis.NextWednesday(), themis.NextWednesday().Add(4*7*24*time.Hour)) sched, err := store.GetSchedule(ctx, themis.NextWednesday(nil), themis.NextWednesday(nil).Add(4*7*24*time.Hour))
if err != nil { if err != nil {
if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource, Type: discordgo.InteractionResponseChannelMessageWithSource,
@ -643,7 +643,7 @@ func main() {
"absent": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) error { "absent": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) error {
var rawDate string var rawDate string
if len(i.ApplicationCommandData().Options) == 0 { if len(i.ApplicationCommandData().Options) == 0 {
rawDate = themis.NextWednesday().Format(time.DateOnly) rawDate = themis.NextWednesday(nil).Format(time.DateOnly)
} else { } else {
rawDate = i.ApplicationCommandData().Options[0].StringValue() rawDate = i.ApplicationCommandData().Options[0].StringValue()
} }
@ -675,17 +675,17 @@ func main() {
return nil return nil
} }
if date.Weekday() != time.Monday { if date.Weekday() != time.Wednesday {
if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource, Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{ Data: &discordgo.InteractionResponseData{
Flags: discordgo.MessageFlagsEphemeral, Flags: discordgo.MessageFlagsEphemeral,
Content: "The date you provided is not a Monday.", Content: "The date you provided is not a Wednesday.",
}, },
}); err != nil { }); err != nil {
return fmt.Errorf("failed to respond to interaction: %w", err) return fmt.Errorf("failed to respond to interaction: %w", err)
} }
// TODO(wperron) suggest Mondays before and after? // TODO(wperron) suggest Wednesdays before and after?
return nil return nil
} }
@ -739,7 +739,7 @@ func main() {
defer span.End() defer span.End()
log.Info().Msg("sending weekly reminder") log.Info().Msg("sending weekly reminder")
absentees, err := store.GetAbsentees(ctx, themis.NextWednesday()) absentees, err := store.GetAbsentees(ctx, themis.NextWednesday(nil))
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to get absentees for next session") log.Error().Err(err).Msg("failed to get absentees for next session")
return return
@ -753,7 +753,7 @@ func main() {
var msg string var msg string
var components []discordgo.MessageComponent var components []discordgo.MessageComponent
if len(absentees) == 0 { if len(absentees) == 0 {
msg = "Everybody can make it next Monday, see you then! 🎉" msg = "Everybody can make it next Wednesday, see you then! 🎉"
components = []discordgo.MessageComponent{ components = []discordgo.MessageComponent{
discordgo.ActionsRow{ discordgo.ActionsRow{
Components: []discordgo.MessageComponent{ Components: []discordgo.MessageComponent{
@ -770,7 +770,7 @@ func main() {
}, },
} }
} else { } else {
msg = fmt.Sprintf("%s can't make it next Monday. 🙁", themis.FormatStringSlice(absentees)) msg = fmt.Sprintf("%s can't make it next Wednesday. 🙁", themis.FormatStringSlice(absentees))
} }
_, err = discord.ChannelMessageSendComplex(channelId, &discordgo.MessageSend{ _, err = discord.ChannelMessageSendComplex(channelId, &discordgo.MessageSend{
@ -884,7 +884,7 @@ func registerHandlers(sess *discordgo.Session, handlers map[string]Handler) {
userId := i.Member.User.ID userId := i.Member.User.ID
log.Info().Ctx(ctx).Str("message_component", "schedule-response").Str("userid", userId).Msg("handling message component interaction") log.Info().Ctx(ctx).Str("message_component", "schedule-response").Str("userid", userId).Msg("handling message component interaction")
if err := store.AddAbsence(ctx, themis.NextWednesday(), userId); err != nil { if err := store.AddAbsence(ctx, themis.NextWednesday(nil), userId); err != nil {
if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource, Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{ Data: &discordgo.InteractionResponseData{

@ -26,7 +26,7 @@ func NewNotifier(c chan context.Context) *Notifier {
} }
func (n *Notifier) Start(ctx context.Context) { func (n *Notifier) Start(ctx context.Context) {
m := NextWednesday() m := NextWednesday(nil)
sat := m.AddDate(0, 0, -4) sat := m.AddDate(0, 0, -4)
if sat.Before(time.Now()) { if sat.Before(time.Now()) {
sat = sat.AddDate(0, 0, 7) sat = sat.AddDate(0, 0, 7)
@ -34,7 +34,7 @@ func (n *Notifier) Start(ctx context.Context) {
t, err := time.ParseInLocation(time.DateTime, fmt.Sprintf("%s 17:00:00", sat.Format(time.DateOnly)), loc) t, err := time.ParseInLocation(time.DateTime, fmt.Sprintf("%s 17:00:00", sat.Format(time.DateOnly)), loc)
if err != nil { if err != nil {
panic("failed to parse next monday notif time. this is likely a bug.") panic("failed to parse next wednesday notif time. this is likely a bug.")
} }
log.Debug().Time("next", t).Msg("starting notifier instance") log.Debug().Time("next", t).Msg("starting notifier instance")

@ -2,16 +2,22 @@ package themis
import "time" import "time"
var now func() time.Time var defaultClock Clock = DefaultClock{}
func init() { type Clock interface {
now = time.Now Now() time.Time
} }
func NextMonday() time.Time { type DefaultClock struct{}
return now().AddDate(0, 0, int((8-now().Weekday())%7))
func (DefaultClock) Now() time.Time {
return time.Now()
} }
func NextWednesday() time.Time { func NextWednesday(clock Clock) time.Time {
return now().AddDate(0, 0, int((10-now().Weekday())%7)) if clock == nil {
clock = defaultClock
}
now := clock.Now()
return now.AddDate(0, 0, int((10-now.Weekday())%7))
} }

@ -4,42 +4,56 @@ import (
"reflect" "reflect"
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/require"
) )
func TestNextMonday(t *testing.T) { type TestClock struct {
now time.Time
}
func (c TestClock) Now() time.Time {
return c.now
}
func TestNextWednesday(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
seed string seed string
want string want string
}{ }{
{ {
name: "on monday", name: "on wednesday",
seed: "2023-11-13T15:04:05Z07:00", seed: "2023-11-15T15:04:05Z",
want: "2023-11-13T15:04:05Z07:00", want: "2023-11-15T15:04:05Z",
}, },
{ {
name: "on sunday", name: "on sunday",
seed: "2023-11-12T15:04:05Z07:00", seed: "2023-11-12T15:04:05Z",
want: "2023-11-13T15:04:05Z07:00", want: "2023-11-15T15:04:05Z",
}, },
{ {
name: "on tuesday", name: "on thursday",
seed: "2023-11-14T15:04:05Z07:00", seed: "2023-11-16T15:04:05Z",
want: "2023-11-20T15:04:05Z07:00", want: "2023-11-22T15:04:05Z",
}, },
{ {
name: "on saturday", name: "on saturday",
seed: "2023-11-18T15:04:05Z07:00", seed: "2023-11-18T15:04:05Z",
want: "2023-11-20T15:04:05Z07:00", want: "2023-11-22T15:04:05Z",
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
seedt, _ := time.Parse(time.RFC3339, tt.seed) seedt, err := time.Parse(time.RFC3339, tt.seed)
now = func() time.Time { return seedt } require.NoError(t, err)
wantt, _ := time.Parse(time.RFC3339, tt.want)
if got := NextMonday(); !reflect.DeepEqual(got, wantt) { wantt, err := time.Parse(time.RFC3339, tt.want)
t.Errorf("NextMonday() = %v, want %v", got, wantt) require.NoError(t, err)
testClock := TestClock{now: seedt}
if got := NextWednesday(testClock); !reflect.DeepEqual(got, wantt) {
t.Errorf("NextWednesday() = %v, want %v", got, wantt)
} }
}) })
} }

Loading…
Cancel
Save