diff --git a/churros.go b/churros.go index 69b972fd93c9d082eed31bd6ba5ee318e1a042b4..9d52447e45ee23a1bc965acab688a268abb73b97 100644 --- a/churros.go +++ b/churros.go @@ -48,12 +48,31 @@ func (id *ChurrosId) UnmarshalText(text []byte) error { } func (msg Message) CreateInDatabaseNotifications(groupId string, subs []Subscription) { - if config.DryRunMode { + if config.DryRunMode && len(config.DryRunExceptions) == 0 { ll.Warn("dry run mode enabled, not creating notifications in database") return } + + subsFilter := func(sub Subscription) bool { return true } + + if len(config.DryRunExceptions) > 0 && config.DryRunMode { + ll.Warn("dry run mode enabled: only creating notifications in database for %+v", config.DryRunExceptions) + subsFilter = func(sub Subscription) bool { + for _, username := range config.DryRunExceptions { + if username == sub.Owner.Uid { + return true + } + } + return false + } + } + // Create sequentially: this is not something that has to be done fast, and parallelizing would swamp the database connections for _, sub := range subs { + if !subsFilter(sub) { + continue + } + prisma.Notification.CreateOne( db.Notification.Subscription.Link( db.NotificationSubscription.Endpoint.Equals(sub.Webpush.Endpoint), diff --git a/config.go b/config.go index 8360bf412fe350b6ef5a8d10bce9bfe8dac40e70..e8841334af7200e908c6dc2e48f42265f183be8b 100644 --- a/config.go +++ b/config.go @@ -12,17 +12,18 @@ import ( ) type Configuration struct { - ChurrosDatabaseURL string `env:"DATABASE_URL"` - RedisURL string `env:"REDIS_URL"` - NatsURL string `env:"NATS_URL" envDefault:"nats://localhost:4222"` - VapidPublicKey string `env:"PUBLIC_VAPID_KEY"` - VapidPrivateKey string `env:"VAPID_PRIVATE_KEY"` - ContactEmail string `env:"CONTACT_EMAIL"` - FirebaseServiceAccount string `env:"FIREBASE_SERVICE_ACCOUNT"` - StartupScheduleRestoration string `env:"STARTUP_SCHEDULE_RESTORATION" envDefault:"enabled"` - AppPackageId string `env:"APP_PACKAGE_ID" envDefault:"app.churros"` - HealthCheckPort int `env:"HEALTH_CHECK_PORT" envDefault:"8080"` - DryRunMode bool `env:"DRY_RUN" envDefault:"false"` + ChurrosDatabaseURL string `env:"DATABASE_URL"` + RedisURL string `env:"REDIS_URL"` + NatsURL string `env:"NATS_URL" envDefault:"nats://localhost:4222"` + VapidPublicKey string `env:"PUBLIC_VAPID_KEY"` + VapidPrivateKey string `env:"VAPID_PRIVATE_KEY"` + ContactEmail string `env:"CONTACT_EMAIL"` + FirebaseServiceAccount string `env:"FIREBASE_SERVICE_ACCOUNT"` + StartupScheduleRestoration string `env:"STARTUP_SCHEDULE_RESTORATION" envDefault:"enabled"` + AppPackageId string `env:"APP_PACKAGE_ID" envDefault:"app.churros"` + HealthCheckPort int `env:"HEALTH_CHECK_PORT" envDefault:"8080"` + DryRunMode bool `env:"DRY_RUN" envDefault:"false"` + DryRunExceptions []string `env:"DRY_RUN_EXCEPTIONS"` } func LoadConfiguration() (Configuration, error) { diff --git a/firebase.go b/firebase.go index aa5199b4de50104cf97b90164b290b37da430fe1..d07cef8813a2c5d53906196bc94bc72466e6bdd9 100644 --- a/firebase.go +++ b/firebase.go @@ -32,10 +32,30 @@ func (msg Message) SendToFirebase(groupId string, subs []Subscription) error { return fmt.Errorf("while initializing FCM client: %w", err) } + if config.DryRunMode && len(config.DryRunExceptions) == 0 { + ll.Warn("dry run mode enabled, not sending FCM message to %d tokens", len(subs)) + return nil + } + message := msg.FirebaseMessage(groupId) - tokens := make([]string, len(subs)) - for i, sub := range subs { - tokens[i] = sub.FirebaseToken() + tokens := make([]string, 0, len(subs)) + for _, sub := range subs { + if config.DryRunMode { + exempt := false + for _, username := range config.DryRunExceptions { + if username == sub.Owner.Uid { + exempt = true + } + } + if !exempt { + continue + } + } + tokens = append(tokens, sub.FirebaseToken()) + } + + if config.DryRunMode { + ll.Warn("dry run mode enabled, only sending FCM message to %d tokens (owned by %+v)", len(tokens), config.DryRunExceptions) } for _, tokensChunk := range chunkBy(tokens, MaxTokensPerRequest) { @@ -44,10 +64,6 @@ func (msg Message) SendToFirebase(groupId string, subs []Subscription) error { return } message.Tokens = tokens - if config.DryRunMode { - ll.Warn("dry run mode enabled, not sending FCM message to %d tokens", len(tokens)) - return - } resp, err := fcm.SendEachForMulticast(firebaseCtx, &message) if err != nil { ll.ErrorDisplay("while sending FCM message", err) diff --git a/server/main.go b/server/main.go index 76e9207445a542fbb4e7e66fe6ee24bd7b06aaa1..ee4f24da864a11c59c07204b9071d731dc587dee 100644 --- a/server/main.go +++ b/server/main.go @@ -28,10 +28,12 @@ func main() { config, _ := notella.LoadConfiguration() ll.Info("Server time is %s", time.Now().Format("2006-01-02 15:04:05 -07:00:00")) - if config.DryRunMode { + if config.DryRunMode && len(config.DryRunExceptions) > 0 { + ll.Info("Running [bold]in dry run mode, [red]except for %+v[reset] with") + } else if config.DryRunMode { ll.Info("Running [bold]in dry run mode[reset] with") } else { - ll.Info("Running with config ") + ll.Info("Running with config") } ll.Log("", "reset", "Schedule recovery: [bold][dim]at startup [reset][bold]%s[reset]", config.StartupScheduleRestoration) ll.Log("", "reset", "contact email: [bold]%s[reset]", config.ContactEmail) diff --git a/typescript/configuration.ts b/typescript/configuration.ts index b3637f45d9b17a1ab9b67f87ea6589b099cfc778..b6f44a57eebf80844ebea62ed5f985cfaefe4f59 100644 --- a/typescript/configuration.ts +++ b/typescript/configuration.ts @@ -3,6 +3,7 @@ export interface Configuration { CONTACT_EMAIL: string; DATABASE_URL: string; DRY_RUN: boolean; + DRY_RUN_EXCEPTIONS: string[]; FIREBASE_SERVICE_ACCOUNT: string; HEALTH_CHECK_PORT: number; NATS_URL: string; diff --git a/webpush.go b/webpush.go index 4e2f96c3b4bbcd535829568c83ba5333c746cb25..6ae3833363573e0e6699fe14395cd1b5a903da08 100644 --- a/webpush.go +++ b/webpush.go @@ -77,9 +77,17 @@ func (msg Message) SendWebPush(groupId string, subs []Subscription) error { for _, sub := range subs { go func(wg *sync.WaitGroup, sub Subscription) { if config.DryRunMode { - ll.Warn("dry run mode enabled, not sending webpush notification to %s", sub.Owner.Uid) - wg.Done() - return + exempt := false + for _, username := range config.DryRunExceptions { + if username == sub.Owner.Uid { + exempt = true + } + } + if !exempt { + ll.Warn("dry run mode enabled, not sending webpush notification to %s", sub.Owner.Uid) + wg.Done() + return + } } resp, err := webpush.SendNotification(jsoned, &sub.Webpush, &webpush.Options{ TTL: 30,