Notifier package to interact with gorush notifications (#910)
This commit is contained in:
parent
7aa508765e
commit
6e1fc99365
|
@ -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)
|
||||||
|
}
|
|
@ -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))
|
||||||
|
}
|
Loading…
Reference in New Issue