Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix notifications
Browse files Browse the repository at this point in the history
Zaptoss committed Sep 25, 2024
1 parent fd176f9 commit a5a1237
Showing 6 changed files with 116 additions and 143 deletions.
27 changes: 0 additions & 27 deletions internal/config/creds.go

This file was deleted.

32 changes: 0 additions & 32 deletions internal/config/daily_question_notification.go

This file was deleted.

102 changes: 96 additions & 6 deletions internal/config/daily_questions.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
package config

import (
"context"
"fmt"
"os"
"sync"
"time"

firebase "firebase.google.com/go/v4"
"firebase.google.com/go/v4/messaging"
"gitlab.com/distributed_lab/figure/v3"
"gitlab.com/distributed_lab/kit/kv"
"google.golang.org/api/option"
)

type NotificationConfig struct {
Title string
Body string
// offset from location time
SendAt int

creds []byte
}

type DailyQuestions struct {
Location *time.Location
Location *time.Location
RawLocation int

Notifications *NotificationConfig

deadlines map[string]Deadline
lastDeadline *time.Time
@@ -27,7 +44,13 @@ type Deadline struct {
func (c *config) DailyQuestions() *DailyQuestions {
return c.DailyQuestion.Do(func() interface{} {
var cfg struct {
Timezone int `fig:"timezone"`
Timezone int `fig:"timezone"`
Notifications struct {
Title string `fig:"title,required"`
Body string `fig:"body"`
SendAt int `fig:"send_at"`
Creds string `fig:"creds_file,required"`
} `fig:"notifications,required"`
}

err := figure.Out(&cfg).
@@ -43,15 +66,82 @@ func (c *config) DailyQuestions() *DailyQuestions {

location := time.FixedZone(fmt.Sprint(cfg.Timezone), cfg.Timezone*3600)

return &DailyQuestions{
Location: location,
deadlines: make(map[string]Deadline),
mu: sync.Mutex{},
var notificationsConfig NotificationConfig
notificationsConfig.Title = cfg.Notifications.Title
notificationsConfig.Body = cfg.Notifications.Body
notificationsConfig.SendAt = cfg.Notifications.SendAt

notificationsConfig.creds, err = os.ReadFile(cfg.Notifications.Creds)
if err != nil {
panic(fmt.Errorf("failed to read firebase creds: %w", err))
}

return &DailyQuestions{
Location: location,
RawLocation: cfg.Timezone,
Notifications: &notificationsConfig,
deadlines: make(map[string]Deadline),
mu: sync.Mutex{},
}
}).(*DailyQuestions)
}

func (q *DailyQuestions) SendNotification() error {
ctx := context.Background()
app, err := firebase.NewApp(ctx, nil, option.WithCredentialsJSON(q.Notifications.creds))
if err != nil {
return fmt.Errorf("failed to initialize app: %w", err)
}

msg := q.Notification()

client, err := app.Messaging(ctx)
if err != nil {
return fmt.Errorf("failed to get Messaging client: %w", err)
}

if _, err = client.Send(ctx, msg); err != nil {
return fmt.Errorf("failed to send message: %w", err)
}

return nil
}

func (q *DailyQuestions) Notification() *messaging.Message {
return &messaging.Message{
Topic: "mokalake-rewardable-stage",
APNS: &messaging.APNSConfig{
Headers: map[string]string{
"apns-priority": "10",
},
Payload: &messaging.APNSPayload{
Aps: &messaging.Aps{
MutableContent: true,
Alert: &messaging.ApsAlert{
Title: q.Notifications.Title,
Body: q.Notifications.Body,
},
},
CustomData: map[string]interface{}{
"type": "daily_question",
},
},
},
Android: &messaging.AndroidConfig{
Priority: "high",
Notification: &messaging.AndroidNotification{
Title: q.Notifications.Title,
Body: q.Notifications.Body,
},
Data: map[string]string{
"type": "daily_question",
"title": q.Notifications.Title,
"description": q.Notifications.Body,
},
},
}
}

func (q *DailyQuestions) LocalTime(date time.Time) time.Time {
return date.In(q.Location)
}
12 changes: 4 additions & 8 deletions internal/config/main.go
Original file line number Diff line number Diff line change
@@ -25,8 +25,6 @@ type Config interface {
Levels() *Levels
Verifiers() Verifiers
DailyQuestions() *DailyQuestions
Creds() *Creds
DailyQuestionsNotification() *DailyQuestionsNotification
}

type config struct {
@@ -42,12 +40,10 @@ type config struct {

passport root.VerifierProvider

Cred comfig.Once
DailyQuestionNotification comfig.Once
DailyQuestion comfig.Once
levels comfig.Once
verifier comfig.Once
getter kv.Getter
DailyQuestion comfig.Once
levels comfig.Once
verifier comfig.Once
getter kv.Getter
}

func New(getter kv.Getter) Config {
1 change: 0 additions & 1 deletion internal/service/router.go
Original file line number Diff line number Diff line change
@@ -24,7 +24,6 @@ func Run(ctx context.Context, cfg config.Config) {
handlers.CtxVerifiers(cfg.Verifiers()),
handlers.CtxSigCalculator(cfg.SigCalculator()),
handlers.CtxPollVerifier(cfg.PollVerifier()),
handlers.CtxCreds(cfg.Creds()),
handlers.CtxDailyQuestion(cfg.DailyQuestions()),
handlers.CtxAbstraction(cfg.AbstractionConfig()),
),
85 changes: 16 additions & 69 deletions internal/service/workers/notificationdailyquestion/main.go
Original file line number Diff line number Diff line change
@@ -3,39 +3,39 @@ package notificationdailyquestion
import (
"context"
"fmt"
"log"
"time"

firebase "firebase.google.com/go/v4"
"firebase.google.com/go/v4/messaging"
"github.com/go-co-op/gocron/v2"
"github.com/rarimo/geo-points-svc/internal/config"
"github.com/rarimo/geo-points-svc/internal/data/pg"
"github.com/rarimo/geo-points-svc/internal/service/workers/cleanquestiondeadlines"
"github.com/rarimo/geo-points-svc/internal/service/workers/cron"
"google.golang.org/api/option"
)

func Run(ctx context.Context, cfg config.Config, sig chan struct{}) {
cron.Init(cfg.Log())
logger := cfg.Log().WithField("notification", "daily-questions-notification")
log := cfg.Log().WithField("who", "daily-questions-notification")

dqConfig := cfg.DailyQuestions()
questionsQ := pg.NewDailyQuestionsQ(cfg.DB().Clone())

offset := cfg.DailyQuestions().LocalTime(cleanquestiondeadlines.AtDayStart(time.Now().UTC())).Hour()
_, err := cron.NewJob(
gocron.DailyJob(1, gocron.NewAtTimes(gocron.NewAtTime(uint(offset), 0, 0))),
gocron.DailyJob(1, gocron.NewAtTimes(gocron.NewAtTime(uint(dqConfig.RawLocation+dqConfig.Notifications.SendAt), 0, 0))),
gocron.NewTask(func() {
curQuestion, err := questionsQ.FilterDayQuestions(time.Now().UTC()).Get()
dailyQuestion, err := questionsQ.FilterDayQuestions(AtDayStart(dqConfig.LocalTime(time.Now())).UTC()).Get()
if err != nil {
logger.Fatalf("error getting daily question: %v", err)
log.WithError(err).Error("Failed to get daily question")
return
}
if curQuestion == nil {
logger.Infof("There's no daily question today")
if dailyQuestion == nil {
log.Infof("There's no daily question today")
return
}
sendingNotifications(cfg.Creds().Path, cfg.DailyQuestionsNotification())

if err = dqConfig.SendNotification(); err != nil {
log.WithError(err).Error("Failed to send notification")
return
}

}),
gocron.WithName("daily-questions-notification"),
)
@@ -47,60 +47,7 @@ func Run(ctx context.Context, cfg config.Config, sig chan struct{}) {
cron.Start(ctx)
}

func sendingNotifications(toCreds string, notification *config.DailyQuestionsNotification) {
credFile := toCreds

msg := &messaging.Message{
Topic: "mokalake-rewardable-stage",
APNS: &messaging.APNSConfig{
Headers: map[string]string{
"apns-priority": "10",
},
Payload: &messaging.APNSPayload{
Aps: &messaging.Aps{
MutableContent: true,
Alert: &messaging.ApsAlert{
Title: notification.Title,
Body: notification.Body,
},
},
CustomData: map[string]interface{}{
"type": "daily_question",
},
},
},
Android: &messaging.AndroidConfig{
Priority: "high",
Notification: &messaging.AndroidNotification{
Title: notification.Title,
Body: notification.Body,
},
Data: map[string]string{
"type": "daily_question",
"content": "{\"event_name\": \"early_test\"}", // custim metadata
"title": notification.Title,
"description": notification.Body,
},
},
}

fmt.Printf("%+v\n", msg)

ctx := context.Background()
app, err := firebase.NewApp(ctx, nil, option.WithCredentialsFile(credFile))
if err != nil {
log.Fatalf("failed to initialize app: %v\n", err)
}

client, err := app.Messaging(ctx)
if err != nil {
log.Fatalf("failed to get Messaging client: %v\n", err)
}

response, err := client.Send(ctx, msg)
if err != nil {
log.Fatalf("failed to send message: %v\n", err)
}

log.Printf("Success: %s\n", response)
func AtDayStart(date time.Time) time.Time {
year, month, day := date.Date()
return time.Date(year, month, day, 0, 0, 0, 0, date.Location())
}

0 comments on commit a5a1237

Please sign in to comment.