-
Notifications
You must be signed in to change notification settings - Fork 4
/
message.go
301 lines (242 loc) · 7.93 KB
/
message.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
package hms
import (
"encoding/json"
"errors"
"fmt"
"regexp"
"strconv"
"time"
)
var (
colorPattern = regexp.MustCompile("^#[0-9a-fA-F]{6}$")
)
type TTL struct {
t time.Duration
}
func NewTTL(dur time.Duration) *TTL {
return &TTL{
t: dur,
}
}
func (t TTL) Seconds() float64 {
return t.t.Seconds()
}
func (t TTL) MarshalJSON() ([]byte, error) {
sec := t.Seconds()
if sec > MaxMessageTTLSec {
sec = MaxMessageTTLSec
}
s := fmt.Sprintf("%.2gS", sec)
return json.Marshal(s)
}
// HuaweiMessage represents list of request params and payload for push api
type HuaweiMessage struct {
// ValidateOnly indicates whether a message is test or not.
// Test message is only used to verify format validity and
// not pushed to user device
ValidateOnly bool `json:"validate_only"`
// Push message structure
Message *Message `json:"message"`
}
// TODO: think how rewrite this validation in proper way
func (hr *HuaweiMessage) Validate() error {
// validate field target, one of Token, Topic and Condition must be invoked
if err := validateFieldTarget(hr.Message.Token, hr.Message.Topic, hr.Message.Condition); err != nil {
return err
}
// validate android config
if err := validateAndroidConfig(hr.Message.Android); err != nil {
return err
}
// validate web common config
if err := validateWebPushConfig(hr.Message.WebPush); err != nil {
return err
}
return nil
}
// TODO: understand how this function works on what purpose of that stuff
func validateFieldTarget(token []string, strings ...string) error {
count := 0
if token != nil {
count++
}
for _, s := range strings {
if s != "" {
count++
}
}
if count == 1 {
return nil
}
return errors.New("token, topics or condition must be choice one")
}
type Message struct {
// Custom message payload, which can be a common string or a string in JSON format.
// Example: "your data" or "{'param1':'value1','param2':'value2'}"
// If the message body contains message.data and does not contain message.notification or
// message.android.notification, the message is a data message.
Data string `json:"data,omitempty"`
// Notification message content
Notification *Notification `json:"notification,omitempty"`
// Android push message control
// This parameter is mandatory for Android notification messages.
Android *AndroidConfig `json:"android,omitempty"`
// iOS push message control
// This parameter is mandatory for iOS messages.
// block is empty, because corresponding documentation is missing
Apns interface{} `json:"apns,omitempty"`
// Web app push message control.
// This parameter is mandatory for iOS messages.
WebPush *WebPushConfig `json:"webpush,omitempty"`
// Push token of the target user of a message. You must set one of token, topic, and condition.
// Example: ["pushtoken1","pushtoken2"]
Token []string `json:"token,omitempty"`
// Topic subscribed by the target user of a message.
// (Currently, this parameter only applies to Android apps).
// You must set one of token, topic, and condition.
Topic string `json:"topic,omitempty"`
// Condition (topic combination expression) for sending a message to the target user.
// (Currently, this parameter applies only to Android apps).
// You must set one of token, topic, and condition.
//
// A Boolean expression of target topics can be specified to send messages based on a combination of condition expressions.
// Supported boolean operations:
// '&&': logical AND
// '||': logical OR
// '! ': logical negative
// '()': priority control
// 'in': keywords
// A maximum of five topics can be included in a condition expression.
// "'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"
// The preceding expression indicates that messages are sent to devices that subscribe to topics A and B or topic C. Devices that subscribe to a single topic do not receive the messages.
Condition string `json:"condition,omitempty"`
}
type Notification struct {
// Notification message title.
Title string `json:"title,omitempty"`
// Notification message content.
Body string `json:"body,omitempty"`
// The URL of custom large icon on the right of a notification message.
// If this parameter is not set, the icon is not displayed.
// The URL must be an HTTPS URL, example: https://example.com/image.png
Image string `json:"image,omitempty"`
}
type Visibility string
const (
VisibilityUnspecified Visibility = "VISIBILITY_UNSPECIFIED"
VisibilityPrivate Visibility = "PRIVATE"
VisibilityPublic Visibility = "PUBLIC"
VisibilitySecret Visibility = "SECRET"
)
func (v Visibility) MarshalJSON() ([]byte, error) {
switch v {
case VisibilityUnspecified, VisibilityPrivate, VisibilityPublic, VisibilitySecret:
return json.Marshal(string(v))
}
return nil, errors.New("Invalid visibility type")
}
type AndroidUrgency string
const (
AndroidUrgencyHigh AndroidUrgency = "HIGH"
AndroidUrgencyNormal AndroidUrgency = "NORMAL"
)
func (d AndroidUrgency) MarshalJSON() ([]byte, error) {
switch d {
case AndroidUrgencyHigh, AndroidUrgencyNormal:
return json.Marshal(string(d))
}
return nil, errors.New("Invalid delivery priority type")
}
type NotificationPriority string
const (
NotificationPriorityHigh NotificationPriority = "HIGH"
NotificationPriorityNormal NotificationPriority = "NORMAL"
NotificationPriorityLow NotificationPriority = "LOW"
)
func (p NotificationPriority) MarshalJSON() ([]byte, error) {
switch p {
case NotificationPriorityHigh, NotificationPriorityNormal, NotificationPriorityLow:
return json.Marshal(string(p))
}
return nil, errors.New("Invalid notification priority type")
}
type Urgency string
const (
UrgencyVeryLow Urgency = "very-low"
UrgencyLow Urgency = "low"
UrgencyNormal Urgency = "normal"
UrgencyHigh Urgency = "high"
)
func (u Urgency) MarshalJSON() ([]byte, error) {
switch u {
case UrgencyVeryLow, UrgencyLow, UrgencyNormal, UrgencyHigh:
return json.Marshal(string(u))
}
return nil, errors.New("Invalid urgency type")
}
type TextDirection string
const (
TextDirAuto TextDirection = "auto"
TextDirLtr TextDirection = "ltr"
TextDirRtl TextDirection = "rtl"
)
func (d TextDirection) MarshalJSON() ([]byte, error) {
switch d {
case TextDirAuto, TextDirLtr, TextDirRtl:
return []byte(d), nil
}
return nil, errors.New("Invalid text direction type")
}
type NotificationBarStyle int
const (
NotificationBarStyleDefault NotificationBarStyle = 0
NotificationBarStyleBigText = iota<<1 - 1
NotificationBarStyleInbox
)
func (b NotificationBarStyle) MarshalJSON() ([]byte, error) {
switch b {
case NotificationBarStyleDefault, NotificationBarStyleBigText, NotificationBarStyleInbox:
return []byte(strconv.Itoa(int(b))), nil
}
return nil, errors.New("Invalid notification bar style type")
}
type ClickActionType int
const (
ClickActionTypeIntentOrAction ClickActionType = iota + 1
ClickActionTypeUrl
ClickActionTypeApp
ClickActionTypeRichResource
)
func (a ClickActionType) MarshalJSON() ([]byte, error) {
switch a {
case ClickActionTypeIntentOrAction, ClickActionTypeUrl, ClickActionTypeApp, ClickActionTypeRichResource:
return []byte(strconv.Itoa(int(a))), nil
}
return nil, errors.New("Invalid click action type")
}
type FastAppState int
const (
FastAppStateDevelop FastAppState = iota + 1
FastAppStateProduct
)
func (s FastAppState) MarshalJSON() ([]byte, error) {
switch s {
case FastAppStateDevelop, FastAppStateProduct:
return []byte(strconv.Itoa(int(s))), nil
}
return nil, errors.New("Invalid fast app state type")
}
// NewNotificationMsgRequest will return a new MessageRequest instance with default value to send notification message.
// developers should set at least on of Message.Token or Message.Topic or Message.Condition
func NewNotificationMsgRequest() *HuaweiMessage {
return &HuaweiMessage{
ValidateOnly: false,
Message: &Message{
Data: "This is a transparent message data",
Notification: &Notification{
Title: "notification title",
Body: "This is a notification message body",
},
},
}
}