Skip to content

Commit 1b20f5a

Browse files
authored
Implementing support for APNS content-mutable field (#126)
* Implementing support for APNS content-mutable field * Corrected the mutable-content option name * Renamed CustomFields to CustomData * Added comment
1 parent 6cf2210 commit 1b20f5a

File tree

3 files changed

+68
-23
lines changed

3 files changed

+68
-23
lines changed

messaging/messaging.go

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -214,36 +214,53 @@ func (p *APNSPayload) MarshalJSON() ([]byte, error) {
214214
// Alert may be specified as a string (via the AlertString field), or as a struct (via the Alert
215215
// field).
216216
type Aps struct {
217-
AlertString string `json:"-"`
218-
Alert *ApsAlert `json:"-"`
219-
Badge *int `json:"badge,omitempty"`
220-
Sound string `json:"sound,omitempty"`
221-
ContentAvailable bool `json:"-"`
222-
Category string `json:"category,omitempty"`
223-
ThreadID string `json:"thread-id,omitempty"`
217+
AlertString string
218+
Alert *ApsAlert
219+
Badge *int
220+
Sound string
221+
ContentAvailable bool
222+
MutableContent bool
223+
Category string
224+
ThreadID string
225+
CustomData map[string]interface{}
224226
}
225227

226-
// MarshalJSON marshals an Aps into JSON (for internal use only).
227-
func (a *Aps) MarshalJSON() ([]byte, error) {
228-
type apsAlias Aps
229-
s := &struct {
230-
Alert interface{} `json:"alert,omitempty"`
231-
ContentAvailable *int `json:"content-available,omitempty"`
232-
*apsAlias
233-
}{
234-
apsAlias: (*apsAlias)(a),
235-
}
236-
228+
// standardFields creates a map containing all the fields except the custom data.
229+
func (a *Aps) standardFields() map[string]interface{} {
230+
m := make(map[string]interface{})
237231
if a.Alert != nil {
238-
s.Alert = a.Alert
232+
m["alert"] = a.Alert
239233
} else if a.AlertString != "" {
240-
s.Alert = a.AlertString
234+
m["alert"] = a.AlertString
241235
}
242236
if a.ContentAvailable {
243-
one := 1
244-
s.ContentAvailable = &one
237+
m["content-available"] = 1
245238
}
246-
return json.Marshal(s)
239+
if a.MutableContent {
240+
m["mutable-content"] = 1
241+
}
242+
if a.Badge != nil {
243+
m["badge"] = *a.Badge
244+
}
245+
if a.Sound != "" {
246+
m["sound"] = a.Sound
247+
}
248+
if a.Category != "" {
249+
m["category"] = a.Category
250+
}
251+
if a.ThreadID != "" {
252+
m["thread-id"] = a.ThreadID
253+
}
254+
return m
255+
}
256+
257+
// MarshalJSON marshals an Aps into JSON (for internal use only).
258+
func (a *Aps) MarshalJSON() ([]byte, error) {
259+
m := a.standardFields()
260+
for k, v := range a.CustomData {
261+
m[k] = v
262+
}
263+
return json.Marshal(m)
247264
}
248265

249266
// ApsAlert is the alert payload that can be included in an Aps.

messaging/messaging_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ var validMessages = []struct {
249249
Sound: "s",
250250
ThreadID: "t",
251251
ContentAvailable: true,
252+
MutableContent: true,
252253
},
253254
CustomData: map[string]interface{}{
254255
"k1": "v1",
@@ -269,6 +270,7 @@ var validMessages = []struct {
269270
"sound": "s",
270271
"thread-id": "t",
271272
"content-available": float64(1),
273+
"mutable-content": float64(1),
272274
},
273275
"k1": "v1",
274276
"k2": true,
@@ -288,6 +290,8 @@ var validMessages = []struct {
288290
Sound: "s",
289291
ThreadID: "t",
290292
ContentAvailable: true,
293+
MutableContent: true,
294+
CustomData: map[string]interface{}{"k1": "v1", "k2": 1},
291295
},
292296
},
293297
},
@@ -302,6 +306,9 @@ var validMessages = []struct {
302306
"sound": "s",
303307
"thread-id": "t",
304308
"content-available": float64(1),
309+
"mutable-content": float64(1),
310+
"k1": "v1",
311+
"k2": float64(1),
305312
},
306313
},
307314
},
@@ -471,6 +478,21 @@ var invalidMessages = []struct {
471478
},
472479
want: "multiple alert specifications",
473480
},
481+
{
482+
name: "APNSMultipleFieldSpecifications",
483+
req: &Message{
484+
APNS: &APNSConfig{
485+
Payload: &APNSPayload{
486+
Aps: &Aps{
487+
Category: "category",
488+
CustomData: map[string]interface{}{"category": "category"},
489+
},
490+
},
491+
},
492+
Topic: "topic",
493+
},
494+
want: `multiple specifications for the key "category"`,
495+
},
474496
{
475497
name: "InvalidAPNSTitleLocArgs",
476498
req: &Message{

messaging/messaging_utils.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ func validateAps(aps *Aps) error {
102102
if aps.Alert != nil && aps.AlertString != "" {
103103
return fmt.Errorf("multiple alert specifications")
104104
}
105+
m := aps.standardFields()
106+
for k := range aps.CustomData {
107+
if _, contains := m[k]; contains {
108+
return fmt.Errorf("multiple specifications for the key %q", k)
109+
}
110+
}
105111
return validateApsAlert(aps.Alert)
106112
}
107113
return nil

0 commit comments

Comments
 (0)