From 6e1fc993656bfccf906c7b15e3fe23c326694fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Cidre?= Date: Tue, 8 May 2018 16:30:03 +0200 Subject: [PATCH] Notifier package to interact with gorush notifications (#910) --- notifier/notifier.go | 100 ++++++++++++++++++++++++++++++++++++++ notifier/notifier_test.go | 62 +++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 notifier/notifier.go create mode 100644 notifier/notifier_test.go diff --git a/notifier/notifier.go b/notifier/notifier.go new file mode 100644 index 000000000..634f3551c --- /dev/null +++ b/notifier/notifier.go @@ -0,0 +1,100 @@ +package notifier + +import ( + "bytes" + "encoding/json" + "errors" + "io/ioutil" + "log" + "net/http" +) + +const ( + // IOS identifier for an iOS notification. + IOS = 1 + // Android identifier for an android notification. + Android = 2 + failedPushErrorType = "failed-push" + pushEndpoint = "/api/push" +) + +// Notifier handles android and ios push notifications. +type Notifier struct { + client *http.Client + url string +} + +// New notifier connected to the specified server. +func New(url string) *Notifier { + client := &http.Client{} + + return &Notifier{url: url, client: client} +} + +// Notification details for gorush. +type Notification struct { + Tokens []string `json:"tokens"` + Platform float32 `json:"platform"` + Message string `json:"message"` +} + +type request struct { + Notifications []*Notification `json:"notifications"` +} + +// Response from gorush. +type Response struct { + Logs []struct { + Type string `json:"type"` + Error string `json:"error"` + } `json:"logs"` +} + +// Send a push notification to given devices. +func (n *Notifier) Send(notifications []*Notification) error { + url := n.url + pushEndpoint + r := request{Notifications: notifications} + + body, err := json.Marshal(r) + if err != nil { + return err + } + + res, err := n.doRequest(url, body) + if err != nil { + return err + } + + if len(res.Logs) > 0 { + if res.Logs[0].Type == failedPushErrorType { + return errors.New(res.Logs[0].Error) + } + } + + return err +} + +func (n *Notifier) doRequest(url string, body []byte) (res Response, err error) { + req, err := http.NewRequest("POST", url, bytes.NewBuffer(body)) + if err != nil { + return + } + req.Header.Set("Content-Type", "application/json") + + resp, err := n.client.Do(req) + if err != nil { + return + } + defer func() { + if err := resp.Body.Close(); err != nil { + log.Println(err.Error()) + } + }() + + body, err = ioutil.ReadAll(resp.Body) + if err != nil { + return + } + + return res, json.Unmarshal(body, &res) +} diff --git a/notifier/notifier_test.go b/notifier/notifier_test.go new file mode 100644 index 000000000..c33e95a00 --- /dev/null +++ b/notifier/notifier_test.go @@ -0,0 +1,62 @@ +package notifier + +import ( + "errors" + "log" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/suite" +) + +type NotifierTestSuite struct { + suite.Suite + url string + n *Notifier +} + +func (s *NotifierTestSuite) SetupTest() { + s.url = "http://localhost:3000" + s.n = New(s.url) +} + +var flagtests = []struct { + response string + err error +}{ + { + response: `{"counts":1,"logs":[{"type":"failed-push","platform":"android","token":"1111111","message":"Hello world","error":"invalid registration token"}],"success":"ok"}`, + err: errors.New("invalid registration token"), + }, + { + response: `{"counts":1,"success":"ok"}`, + err: nil, + }, +} + +func (s *NotifierTestSuite) TestSendNotifications() { + for _, tt := range flagtests { + var apiStub = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + if _, err := w.Write([]byte(tt.response)); err != nil { + log.Println(err.Error()) + } + })) + defer apiStub.Close() + + s.n.url = apiStub.URL + notification := Notification{ + Tokens: []string{"t1", "t2"}, + Platform: 2, + Message: "hello world", + } + + err := s.n.Send([]*Notification{¬ification}) + s.Equal(tt.err, err) + } +} + +func TestNotifierTestSuite(t *testing.T) { + suite.Run(t, new(NotifierTestSuite)) +}