fork
Configure Feed
Select the types of activity you want to include in your feed.
Live video on the AT Protocol
fork
Configure Feed
Select the types of activity you want to include in your feed.
1package notifications
2
3import (
4 "encoding/base64"
5 "encoding/json"
6 "fmt"
7
8 firebase "firebase.google.com/go/v4"
9 "firebase.google.com/go/v4/messaging"
10 "golang.org/x/net/context"
11 "google.golang.org/api/option"
12 "stream.place/streamplace/pkg/log"
13)
14
15type FirebaseNotifier interface {
16 Blast(ctx context.Context, tokens []string, golive *NotificationBlast) error
17}
18
19type FirebaseNotifierS struct {
20 app *firebase.App
21}
22
23type GoogleCredential struct {
24 ProjectID string `json:"project_id"`
25}
26
27type NotificationBlast struct {
28 Title string `json:"title"`
29 Body string `json:"body"`
30 Data map[string]string `json:"data"`
31}
32
33func MakeFirebaseNotifier(ctx context.Context, serviceAccountJSONb64 string) (FirebaseNotifier, error) {
34 // string can optionally be base64-encoded
35 serviceAccountJSON := serviceAccountJSONb64
36 dec, err := base64.StdEncoding.DecodeString(serviceAccountJSONb64)
37 if err == nil {
38 // succeeded, cool! use that.
39 serviceAccountJSON = string(dec)
40 }
41 var cred GoogleCredential
42 err = json.Unmarshal([]byte(serviceAccountJSON), &cred)
43 if err != nil {
44 return nil, fmt.Errorf("error trying to discover project_id: %w", err)
45 }
46 conf := &firebase.Config{
47 ProjectID: cred.ProjectID,
48 }
49 opt := option.WithCredentialsJSON([]byte(serviceAccountJSON))
50 app, err := firebase.NewApp(ctx, conf, opt)
51 if err != nil {
52 return nil, fmt.Errorf("failed to initialize Firebase app: %w", err)
53 }
54 return &FirebaseNotifierS{app: app}, nil
55}
56
57// refactor me when we have >500 users
58func (f *FirebaseNotifierS) Blast(ctx context.Context, tokens []string, blast *NotificationBlast) error {
59 client, err := f.app.Messaging(ctx)
60 if err != nil {
61 return err
62 }
63
64 notification := &messaging.MulticastMessage{
65 Tokens: tokens,
66 Data: blast.Data,
67 Notification: &messaging.Notification{
68 Title: blast.Title,
69 Body: blast.Body,
70 },
71 Android: &messaging.AndroidConfig{
72 Priority: "high",
73 Notification: &messaging.AndroidNotification{
74 Sound: "default",
75 },
76 },
77 APNS: &messaging.APNSConfig{
78 Headers: map[string]string{
79 "apns-priority": "10",
80 },
81 Payload: &messaging.APNSPayload{
82 Aps: &messaging.Aps{
83 Sound: "default",
84 },
85 },
86 },
87 }
88 res, err := client.SendEachForMulticast(ctx, notification)
89 if err != nil {
90 return err
91 }
92 log.Log(ctx, "notification blast successful", "successCount", res.SuccessCount, "failureCount", res.FailureCount)
93 return nil
94}