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