Skip to content

Commit

Permalink
fix: use mutable content and content available when set. (#805)
Browse files Browse the repository at this point in the history
* fix: use mutable content and content available when set.

Content available is for background notifications hence the notification
shouldn't have an alert or sound.
Ref:
https://developer.apple.com/documentation/usernotifications/generating-a-remote-notification

* fix: put correct header for IOS push notifications.

* fix: improve content-available support.

* feat: only log FCM message in development mode.
  • Loading branch information
hchienjo authored Sep 12, 2024
1 parent 6d8402b commit 3c3a5d3
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 18 deletions.
72 changes: 61 additions & 11 deletions notify/notification_fcm.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,29 +74,72 @@ func GetAndroidNotification(req *PushNotification) []*messaging.Message {
if req.Image != "" {
req.Notification.ImageURL = req.Image
}
if req.MutableContent {
req.APNS = &messaging.APNSConfig{
Payload: &messaging.APNSPayload{
Aps: &messaging.Aps{
MutableContent: req.MutableContent,
},
},
}
}
}

// content-available is for background notifications and a badge, alert
// and sound keys should not be present.
// See: https://developer.apple.com/documentation/usernotifications/generating-a-remote-notification
if req.ContentAvailable {
req.APNS = &messaging.APNSConfig{
Headers: map[string]string{
"apns-priority": "5",
},
Payload: &messaging.APNSPayload{
Aps: &messaging.Aps{
ContentAvailable: req.ContentAvailable,
CustomData: req.Data,
},
},
}
}

// Check if the notification has a sound
if req.Sound != nil {
sound, ok := req.Sound.(string)

if req.APNS == nil && ok {
req.APNS = &messaging.APNSConfig{
Payload: &messaging.APNSPayload{
if ok {
switch {
case req.APNS == nil:
req.APNS = &messaging.APNSConfig{
Payload: &messaging.APNSPayload{
Aps: &messaging.Aps{
Sound: sound,
},
},
}
case req.APNS.Payload == nil:
req.APNS.Payload = &messaging.APNSPayload{
Aps: &messaging.Aps{
Sound: sound,
},
},
}
}
}

if req.Android == nil && ok {
req.Android = &messaging.AndroidConfig{
Notification: &messaging.AndroidNotification{
case req.APNS.Payload.Aps == nil:
req.APNS.Payload.Aps = &messaging.Aps{
Sound: sound,
},
}
default:
req.APNS.Payload.Aps.Sound = sound

}

if req.Android == nil {
req.Android = &messaging.AndroidConfig{
Notification: &messaging.AndroidNotification{
Sound: sound,
},
}
}
}

}

// Check if the notification is a topic
Expand Down Expand Up @@ -183,6 +226,13 @@ Retry:
return resp, err
}

if req.Development {
for i, msg := range messages {
m, _ := json.Marshal(msg)
logx.LogAccess.Infof("message #%d - %s", i, m)
}
}

res, err := client.Send(ctx, messages...)
if err != nil {
newErr := fmt.Errorf("fcm service send message error: %v", err)
Expand Down
44 changes: 37 additions & 7 deletions notify/notification_fcm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package notify
import (
"context"
"os"
"reflect"
"testing"

"firebase.google.com/go/v4/messaging"
Expand Down Expand Up @@ -149,13 +150,13 @@ func TestFCMMessage(t *testing.T) {
func TestAndroidNotificationStructure(t *testing.T) {
test := "test"
req := &PushNotification{
Tokens: []string{"a", "b"},
Message: "Welcome",
To: test,
Priority: HIGH,
ContentAvailable: true,
Title: test,
Sound: test,
Tokens: []string{"a", "b"},
Message: "Welcome",
To: test,
Priority: HIGH,
MutableContent: true,
Title: test,
Sound: test,
Data: D{
"a": "1",
"b": 2,
Expand All @@ -177,6 +178,9 @@ func TestAndroidNotificationStructure(t *testing.T) {
assert.Equal(t, "1", messages[0].Data["a"])
assert.Equal(t, "2", messages[0].Data["b"])
assert.Equal(t, "{\"c\":\"3\",\"d\":4}", messages[0].Data["json"])
assert.NotNil(t, messages[0].APNS)
assert.Equal(t, req.Sound, messages[0].APNS.Payload.Aps.Sound)
assert.Equal(t, req.MutableContent, messages[0].APNS.Payload.Aps.MutableContent)

// test empty body
req = &PushNotification{
Expand All @@ -190,3 +194,29 @@ func TestAndroidNotificationStructure(t *testing.T) {

assert.Equal(t, "", messages[0].Notification.Body)
}

func TestAndroidBackgroundNotificationStructure(t *testing.T) {
data := map[string]any{
"a": "1",
"b": 2,
"json": map[string]interface{}{
"c": "3",
"d": 4,
},
}
req := &PushNotification{
Tokens: []string{"a", "b"},
Priority: HIGH,
ContentAvailable: true,
Data: data,
}

messages := GetAndroidNotification(req)

assert.Equal(t, "1", messages[0].Data["a"])
assert.Equal(t, "2", messages[0].Data["b"])
assert.Equal(t, "{\"c\":\"3\",\"d\":4}", messages[0].Data["json"])
assert.NotNil(t, messages[0].APNS)
assert.Equal(t, req.ContentAvailable, messages[0].APNS.Payload.Aps.ContentAvailable)
assert.True(t, reflect.DeepEqual(data, messages[0].APNS.Payload.Aps.CustomData))
}

0 comments on commit 3c3a5d3

Please sign in to comment.