Notifier package to interact with gorush notifications (#910)

This commit is contained in:
Adrià Cidre 2018-05-08 16:30:03 +02:00 committed by GitHub
parent 7aa508765e
commit 6e1fc99365
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 162 additions and 0 deletions

100
notifier/notifier.go Normal file
View File

@ -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)
}

62
notifier/notifier_test.go Normal file
View File

@ -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{&notification})
s.Equal(tt.err, err)
}
}
func TestNotifierTestSuite(t *testing.T) {
suite.Run(t, new(NotifierTestSuite))
}