status-im/status-go

View on GitHub
notifier/notifier.go

Summary

Maintainability
A
0 mins
Test Coverage
C
71%
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)
}