From 99566c8bf9138c2cbbdc9687e5e45eac996f0df9 Mon Sep 17 00:00:00 2001 From: jayme-github Date: Tue, 23 Jun 2020 20:11:03 +0200 Subject: [PATCH] Switch to sending data messages only Handling of notification messages is quite inconsistent (at least on android). Send the payload in data only and let the app handle the notification locally. Add pageTime to data payload (Unix epoch UTC). --- fcm.go | 35 ++++++++++++++++++++++------------- handler.go | 27 +++++++++++++++++---------- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/fcm.go b/fcm.go index 9379825..a264ac0 100644 --- a/fcm.go +++ b/fcm.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" tmpltext "text/template" + "time" "github.com/prometheus/alertmanager/template" "golang.org/x/net/context" @@ -59,18 +60,15 @@ func NewMessaging() (*messaging.Client, error) { return client, err } -// NewMessage returns a new FCM message struct -func NewMessage(topic, title, body string) *messaging.Message { +func NewDataMessage(topic, title, body string) *messaging.Message { + unixMillisecondsUTC := time.Now().UTC().UnixNano() / 1000000 + data := map[string]string{ + "title": title, + "body": body, + "pageTime": string(unixMillisecondsUTC), + } return &messaging.Message{ - Notification: &messaging.Notification{ - Title: title, - Body: body, - }, - Data: map[string]string{ - "title": title, - "body": body, - "click_action": "FLUTTER_NOTIFICATION_CLICK", - }, + Data: data, Topic: topic, // https://firebase.google.com/docs/cloud-messaging/concept-options#setting-the-priority-of-a-message Android: &messaging.AndroidConfig{ @@ -79,7 +77,18 @@ func NewMessage(topic, title, body string) *messaging.Message { } } -// NewMessageFromAlertmanagerDats returns a new FCM message from alertmanager POST data +// NewNoficationMessage returns a new FCM message including notificaton data +func NewNoficationMessage(topic, title, body string) *messaging.Message { + message := NewDataMessage(topic, title, body) + message.Notification = &messaging.Notification{ + Title: title, + Body: body, + } + message.Data["click_action"] = "FLUTTER_NOTIFICATION_CLICK" + return message +} + +// NewMessageFromAlertmanagerDats returns a new FCM data message from alertmanager POST data func NewMessageFromAlertmanagerData(topic string, m *template.Data) (*messaging.Message, error) { title, err := tmpltextExecuteToString(tmplTitle, m) if err != nil { @@ -91,7 +100,7 @@ func NewMessageFromAlertmanagerData(topic string, m *template.Data) (*messaging. return nil, &TemplateError{Type: "body", Err: err} } - return NewMessage(topic, title, body), nil + return NewDataMessage(topic, title, body), nil } func tmpltextExecuteToString(tmpl *tmpltext.Template, data interface{}) (string, error) { diff --git a/handler.go b/handler.go index 85b2fe8..c684920 100644 --- a/handler.go +++ b/handler.go @@ -8,6 +8,7 @@ import ( "net/http" "strconv" + "firebase.google.com/go/messaging" "github.com/julienschmidt/httprouter" "github.com/prometheus/alertmanager/template" ) @@ -19,8 +20,9 @@ type JSONResponse struct { } type genericJSONRequest struct { - Title string - Body string + Title string + Body string + Notification bool } func indexHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { @@ -36,6 +38,7 @@ func indexHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { } func genericHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { + var message *messaging.Message data, err := readGenericRequestBody(req) if err != nil { log.Printf("Error parsing request body: %v", err) @@ -44,7 +47,11 @@ func genericHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Para } topic := getParamTopic(ps) - message := NewMessage(topic, data.Title, data.Body) + if data.Notification { + message = NewNoficationMessage(topic, data.Title, data.Body) + } else { + message = NewDataMessage(topic, data.Title, data.Body) + } msg, err := fcmClient.Send(req.Context(), message) fcmMessages.WithLabelValues(ps.MatchedRoutePath(), topic).Inc() @@ -60,13 +67,6 @@ func genericHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Para ) } -func readGenericRequestBody(req *http.Request) (*genericJSONRequest, error) { - defer req.Body.Close() - data := genericJSONRequest{} - err := json.NewDecoder(req.Body).Decode(&data) - return &data, err -} - func alertHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { templateData, err := readAlertRequestBody(req) if err != nil { @@ -99,6 +99,13 @@ func getParamTopic(ps httprouter.Params) string { return topic } +func readGenericRequestBody(req *http.Request) (*genericJSONRequest, error) { + defer req.Body.Close() + data := genericJSONRequest{} + err := json.NewDecoder(req.Body).Decode(&data) + return &data, err +} + func readAlertRequestBody(req *http.Request) (*template.Data, error) { defer req.Body.Close() data := template.Data{}