101 lines
1.9 KiB
Go
101 lines
1.9 KiB
Go
|
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)
|
||
|
}
|