From b173c06c4ae1694666a0a747a7144b05f130e3cf Mon Sep 17 00:00:00 2001 From: hiranya911 Date: Thu, 22 Mar 2018 14:54:33 -0700 Subject: [PATCH 1/4] Implementing support for APNS content-mutable field --- messaging/messaging.go | 62 +++++++++++++++++++++++------------- messaging/messaging_test.go | 22 +++++++++++++ messaging/messaging_utils.go | 6 ++++ 3 files changed, 67 insertions(+), 23 deletions(-) diff --git a/messaging/messaging.go b/messaging/messaging.go index fb6fa5dd..d1d25c73 100644 --- a/messaging/messaging.go +++ b/messaging/messaging.go @@ -214,36 +214,52 @@ func (p *APNSPayload) MarshalJSON() ([]byte, error) { // Alert may be specified as a string (via the AlertString field), or as a struct (via the Alert // field). type Aps struct { - AlertString string `json:"-"` - Alert *ApsAlert `json:"-"` - Badge *int `json:"badge,omitempty"` - Sound string `json:"sound,omitempty"` - ContentAvailable bool `json:"-"` - Category string `json:"category,omitempty"` - ThreadID string `json:"thread-id,omitempty"` + AlertString string + Alert *ApsAlert + Badge *int + Sound string + ContentAvailable bool + ContentMutable bool + Category string + ThreadID string + CustomFields map[string]interface{} } -// MarshalJSON marshals an Aps into JSON (for internal use only). -func (a *Aps) MarshalJSON() ([]byte, error) { - type apsAlias Aps - s := &struct { - Alert interface{} `json:"alert,omitempty"` - ContentAvailable *int `json:"content-available,omitempty"` - *apsAlias - }{ - apsAlias: (*apsAlias)(a), - } - +func (a *Aps) standardFields() map[string]interface{} { + m := make(map[string]interface{}) if a.Alert != nil { - s.Alert = a.Alert + m["alert"] = a.Alert } else if a.AlertString != "" { - s.Alert = a.AlertString + m["alert"] = a.AlertString } if a.ContentAvailable { - one := 1 - s.ContentAvailable = &one + m["content-available"] = 1 } - return json.Marshal(s) + if a.ContentMutable { + m["content-mutable"] = 1 + } + if a.Badge != nil { + m["badge"] = *a.Badge + } + if a.Sound != "" { + m["sound"] = a.Sound + } + if a.Category != "" { + m["category"] = a.Category + } + if a.ThreadID != "" { + m["thread-id"] = a.ThreadID + } + return m +} + +// MarshalJSON marshals an Aps into JSON (for internal use only). +func (a *Aps) MarshalJSON() ([]byte, error) { + m := a.standardFields() + for k, v := range a.CustomFields { + m[k] = v + } + return json.Marshal(m) } // ApsAlert is the alert payload that can be included in an Aps. diff --git a/messaging/messaging_test.go b/messaging/messaging_test.go index 1d6d3ad5..08a1d5d7 100644 --- a/messaging/messaging_test.go +++ b/messaging/messaging_test.go @@ -249,6 +249,7 @@ var validMessages = []struct { Sound: "s", ThreadID: "t", ContentAvailable: true, + ContentMutable: true, }, CustomData: map[string]interface{}{ "k1": "v1", @@ -269,6 +270,7 @@ var validMessages = []struct { "sound": "s", "thread-id": "t", "content-available": float64(1), + "content-mutable": float64(1), }, "k1": "v1", "k2": true, @@ -288,6 +290,8 @@ var validMessages = []struct { Sound: "s", ThreadID: "t", ContentAvailable: true, + ContentMutable: true, + CustomFields: map[string]interface{}{"k1": "v1", "k2": 1}, }, }, }, @@ -302,6 +306,9 @@ var validMessages = []struct { "sound": "s", "thread-id": "t", "content-available": float64(1), + "content-mutable": float64(1), + "k1": "v1", + "k2": float64(1), }, }, }, @@ -471,6 +478,21 @@ var invalidMessages = []struct { }, want: "multiple alert specifications", }, + { + name: "APNSMultipleFieldSpecifications", + req: &Message{ + APNS: &APNSConfig{ + Payload: &APNSPayload{ + Aps: &Aps{ + Category: "category", + CustomFields: map[string]interface{}{"category": "category"}, + }, + }, + }, + Topic: "topic", + }, + want: `multiple specifications for the key "category"`, + }, { name: "InvalidAPNSTitleLocArgs", req: &Message{ diff --git a/messaging/messaging_utils.go b/messaging/messaging_utils.go index ffd4df95..21e97177 100644 --- a/messaging/messaging_utils.go +++ b/messaging/messaging_utils.go @@ -102,6 +102,12 @@ func validateAps(aps *Aps) error { if aps.Alert != nil && aps.AlertString != "" { return fmt.Errorf("multiple alert specifications") } + m := aps.standardFields() + for k := range aps.CustomFields { + if _, contains := m[k]; contains { + return fmt.Errorf("multiple specifications for the key %q", k) + } + } return validateApsAlert(aps.Alert) } return nil From 23e5476a39d11518098e6421b7e3a6ab34eb863a Mon Sep 17 00:00:00 2001 From: hiranya911 Date: Thu, 22 Mar 2018 15:47:51 -0700 Subject: [PATCH 2/4] Corrected the mutable-content option name --- messaging/messaging.go | 6 +++--- messaging/messaging_test.go | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/messaging/messaging.go b/messaging/messaging.go index d1d25c73..b4a7b951 100644 --- a/messaging/messaging.go +++ b/messaging/messaging.go @@ -219,7 +219,7 @@ type Aps struct { Badge *int Sound string ContentAvailable bool - ContentMutable bool + MutableContent bool Category string ThreadID string CustomFields map[string]interface{} @@ -235,8 +235,8 @@ func (a *Aps) standardFields() map[string]interface{} { if a.ContentAvailable { m["content-available"] = 1 } - if a.ContentMutable { - m["content-mutable"] = 1 + if a.MutableContent { + m["mutable-content"] = 1 } if a.Badge != nil { m["badge"] = *a.Badge diff --git a/messaging/messaging_test.go b/messaging/messaging_test.go index 08a1d5d7..8db6bfc0 100644 --- a/messaging/messaging_test.go +++ b/messaging/messaging_test.go @@ -249,7 +249,7 @@ var validMessages = []struct { Sound: "s", ThreadID: "t", ContentAvailable: true, - ContentMutable: true, + MutableContent: true, }, CustomData: map[string]interface{}{ "k1": "v1", @@ -270,7 +270,7 @@ var validMessages = []struct { "sound": "s", "thread-id": "t", "content-available": float64(1), - "content-mutable": float64(1), + "mutable-content": float64(1), }, "k1": "v1", "k2": true, @@ -290,7 +290,7 @@ var validMessages = []struct { Sound: "s", ThreadID: "t", ContentAvailable: true, - ContentMutable: true, + MutableContent: true, CustomFields: map[string]interface{}{"k1": "v1", "k2": 1}, }, }, @@ -306,7 +306,7 @@ var validMessages = []struct { "sound": "s", "thread-id": "t", "content-available": float64(1), - "content-mutable": float64(1), + "mutable-content": float64(1), "k1": "v1", "k2": float64(1), }, From 5019b5f1b87a7dc7ce21d8bb09590921d9320425 Mon Sep 17 00:00:00 2001 From: hiranya911 Date: Thu, 5 Apr 2018 14:42:36 -0700 Subject: [PATCH 3/4] Renamed CustomFields to CustomData --- messaging/messaging.go | 4 ++-- messaging/messaging_test.go | 6 +++--- messaging/messaging_utils.go | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/messaging/messaging.go b/messaging/messaging.go index 585020e6..3c2980a7 100644 --- a/messaging/messaging.go +++ b/messaging/messaging.go @@ -222,7 +222,7 @@ type Aps struct { MutableContent bool Category string ThreadID string - CustomFields map[string]interface{} + CustomData map[string]interface{} } func (a *Aps) standardFields() map[string]interface{} { @@ -256,7 +256,7 @@ func (a *Aps) standardFields() map[string]interface{} { // MarshalJSON marshals an Aps into JSON (for internal use only). func (a *Aps) MarshalJSON() ([]byte, error) { m := a.standardFields() - for k, v := range a.CustomFields { + for k, v := range a.CustomData { m[k] = v } return json.Marshal(m) diff --git a/messaging/messaging_test.go b/messaging/messaging_test.go index b564686e..8f66cb93 100644 --- a/messaging/messaging_test.go +++ b/messaging/messaging_test.go @@ -291,7 +291,7 @@ var validMessages = []struct { ThreadID: "t", ContentAvailable: true, MutableContent: true, - CustomFields: map[string]interface{}{"k1": "v1", "k2": 1}, + CustomData: map[string]interface{}{"k1": "v1", "k2": 1}, }, }, }, @@ -484,8 +484,8 @@ var invalidMessages = []struct { APNS: &APNSConfig{ Payload: &APNSPayload{ Aps: &Aps{ - Category: "category", - CustomFields: map[string]interface{}{"category": "category"}, + Category: "category", + CustomData: map[string]interface{}{"category": "category"}, }, }, }, diff --git a/messaging/messaging_utils.go b/messaging/messaging_utils.go index 21e97177..8e0cb0e9 100644 --- a/messaging/messaging_utils.go +++ b/messaging/messaging_utils.go @@ -103,7 +103,7 @@ func validateAps(aps *Aps) error { return fmt.Errorf("multiple alert specifications") } m := aps.standardFields() - for k := range aps.CustomFields { + for k := range aps.CustomData { if _, contains := m[k]; contains { return fmt.Errorf("multiple specifications for the key %q", k) } From bdcd724838cce9308b0f252d71513f1323de3db5 Mon Sep 17 00:00:00 2001 From: hiranya911 Date: Thu, 5 Apr 2018 16:37:47 -0700 Subject: [PATCH 4/4] Added comment --- messaging/messaging.go | 1 + 1 file changed, 1 insertion(+) diff --git a/messaging/messaging.go b/messaging/messaging.go index 3c2980a7..65099e80 100644 --- a/messaging/messaging.go +++ b/messaging/messaging.go @@ -225,6 +225,7 @@ type Aps struct { CustomData map[string]interface{} } +// standardFields creates a map containing all the fields except the custom data. func (a *Aps) standardFields() map[string]interface{} { m := make(map[string]interface{}) if a.Alert != nil {