feat: check unused package (#232)
* feat: check unused package update edganiukov/fcm to appleboy/go-fcm * update readme Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> * update comment Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
This commit is contained in:
21
vendor/github.com/appleboy/go-fcm/LICENSE
generated
vendored
Normal file
21
vendor/github.com/appleboy/go-fcm/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Eduard Ganiukov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
64
vendor/github.com/appleboy/go-fcm/README.md
generated
vendored
Normal file
64
vendor/github.com/appleboy/go-fcm/README.md
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
# go-fcm
|
||||
|
||||
[](https://godoc.org/github.com/edganiukov/fcm)
|
||||
[](https://travis-ci.org/edganiukov/fcm)
|
||||
[](https://goreportcard.com/report/github.com/edganiukov/fcm)
|
||||
|
||||
This project was forked from [github.com/edganiukov/fcmfcm](https://github.com/edganiukov/fcm).
|
||||
|
||||
Golang client library for Firebase Cloud Messaging. Implemented only [HTTP client](https://firebase.google.com/docs/cloud-messaging/http-server-ref#downstream).
|
||||
|
||||
More information on [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/)
|
||||
|
||||
## Getting Started
|
||||
|
||||
To install fcm, use `go get`:
|
||||
|
||||
```bash
|
||||
go get github.com/appleboy/go-fcm
|
||||
```
|
||||
|
||||
or `govendor`:
|
||||
|
||||
```bash
|
||||
govendor fetch github.com/appleboy/go-fcm
|
||||
```
|
||||
|
||||
or other tool for vendoring.
|
||||
|
||||
## Sample Usage
|
||||
|
||||
Here is a simple example illustrating how to use FCM library:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/edganiukov/fcm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Create the message to be sent.
|
||||
msg := &fcm.Message{
|
||||
Token: "sample_device_token",
|
||||
Data: map[string]interface{}{
|
||||
"foo": "bar",
|
||||
}
|
||||
}
|
||||
|
||||
// Create a FCM client to send the message.
|
||||
client := fcm.NewClient("sample_api_key")
|
||||
|
||||
// Send the message and receive the response without retries.
|
||||
response, err := client.Send(msg)
|
||||
if err != nil {
|
||||
/* ... */
|
||||
}
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### TODO:
|
||||
---------
|
||||
- [ ] Retry only failed messages while multicast messaging.
|
||||
133
vendor/github.com/appleboy/go-fcm/client.go
generated
vendored
Normal file
133
vendor/github.com/appleboy/go-fcm/client.go
generated
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
package fcm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultEndpoint contains endpoint URL of FCM service.
|
||||
DefaultEndpoint = "https://fcm.googleapis.com/fcm/send"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidAPIKey occurs if API key is not set.
|
||||
ErrInvalidAPIKey = errors.New("client API Key is invalid")
|
||||
)
|
||||
|
||||
// Client abstracts the interaction between the application server and the
|
||||
// FCM server via HTTP protocol. The developer must obtain an API key from the
|
||||
// Google APIs Console page and pass it to the `Client` so that it can
|
||||
// perform authorized requests on the application server's behalf.
|
||||
// To send a message to one or more devices use the Client's Send.
|
||||
//
|
||||
// If the `HTTP` field is nil, a zeroed http.Client will be allocated and used
|
||||
// to send messages.
|
||||
type Client struct {
|
||||
apiKey string
|
||||
client *http.Client
|
||||
endpoint string
|
||||
}
|
||||
|
||||
// NewClient creates new Firebase Cloud Messaging Client based on API key and
|
||||
// with default endpoint and http client.
|
||||
func NewClient(apiKey string, opts ...Option) (*Client, error) {
|
||||
if apiKey == "" {
|
||||
return nil, ErrInvalidAPIKey
|
||||
}
|
||||
c := &Client{
|
||||
apiKey: apiKey,
|
||||
endpoint: DefaultEndpoint,
|
||||
client: &http.Client{},
|
||||
}
|
||||
for _, o := range opts {
|
||||
if err := o(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Send sends a message to the FCM server without retrying in case of service
|
||||
// unavailability. A non-nil error is returned if a non-recoverable error
|
||||
// occurs (i.e. if the response status is not "200 OK").
|
||||
func (c *Client) Send(msg *Message) (*Response, error) {
|
||||
// validate
|
||||
if err := msg.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// marshal message
|
||||
data, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.send(data)
|
||||
}
|
||||
|
||||
// SendWithRetry sends a message to the FCM server with defined number of
|
||||
// retrying in case of temporary error.
|
||||
func (c *Client) SendWithRetry(msg *Message, retryAttempts int) (*Response, error) {
|
||||
// validate
|
||||
if err := msg.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// marshal message
|
||||
data, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
err = retry(func() error {
|
||||
var err error
|
||||
resp, err = c.send(data)
|
||||
return err
|
||||
}, retryAttempts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// send sends a request.
|
||||
func (c *Client) send(data []byte) (*Response, error) {
|
||||
// create request
|
||||
req, err := http.NewRequest("POST", c.endpoint, bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// add headers
|
||||
req.Header.Add("Authorization", fmt.Sprintf("key=%s", c.apiKey))
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
// execute request
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, connectionError(err.Error())
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// check response status
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
if resp.StatusCode >= http.StatusInternalServerError {
|
||||
return nil, serverError(fmt.Sprintf("%d error: %s", resp.StatusCode, resp.Status))
|
||||
}
|
||||
return nil, fmt.Errorf("%d error: %s", resp.StatusCode, resp.Status)
|
||||
}
|
||||
|
||||
// build return
|
||||
response := new(Response)
|
||||
if err := json.NewDecoder(resp.Body).Decode(response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
77
vendor/github.com/appleboy/go-fcm/message.go
generated
vendored
Normal file
77
vendor/github.com/appleboy/go-fcm/message.go
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
package fcm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidMessage occurs if push notitication message is nil.
|
||||
ErrInvalidMessage = errors.New("message is invalid")
|
||||
|
||||
// ErrInvalidTarget occurs if message topic is empty.
|
||||
ErrInvalidTarget = errors.New("topic is invalid or registration ids are not set")
|
||||
|
||||
// ErrToManyRegIDs occurs when registration ids more then 1000.
|
||||
ErrToManyRegIDs = errors.New("too many registrations ids")
|
||||
|
||||
// ErrInvalidTimeToLive occurs if TimeToLive more then 2419200.
|
||||
ErrInvalidTimeToLive = errors.New("messages time-to-live is invalid")
|
||||
)
|
||||
|
||||
// Notification specifies the predefined, user-visible key-value pairs of the
|
||||
// notification payload.
|
||||
type Notification struct {
|
||||
Title string `json:"title,omitempty"`
|
||||
Body string `json:"body,omitempty"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
Sound string `json:"sound,omitempty"`
|
||||
Badge string `json:"badge,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
Color string `json:"color,omitempty"`
|
||||
ClickAction string `json:"click_action,omitempty"`
|
||||
BodyLocKey string `json:"body_loc_key,omitempty"`
|
||||
BodyLocArgs string `json:"body_loc_args,omitempty"`
|
||||
TitleLocKey string `json:"title_loc_key,omitempty"`
|
||||
TitleLocArgs string `json:"title_loc_args,omitempty"`
|
||||
}
|
||||
|
||||
// Message represents list of targets, options, and payload for HTTP JSON
|
||||
// messages.
|
||||
type Message struct {
|
||||
To string `json:"to,omitempty"`
|
||||
RegistrationIDs []string `json:"registration_ids,omitempty"`
|
||||
Condition string `json:"condition,omitempty"`
|
||||
CollapseKey string `json:"collapse_key,omitempty"`
|
||||
Priority string `json:"priority,omitempty"`
|
||||
ContentAvailable bool `json:"content_available,omitempty"`
|
||||
DelayWhileIdle bool `json:"delay_while_idle,omitempty"`
|
||||
TimeToLive *uint `json:"time_to_live,omitempty"`
|
||||
DeliveryReceiptRequested bool `json:"delivery_receipt_requested,omitempty"`
|
||||
DryRun bool `json:"dry_run,omitempty"`
|
||||
RestrictedPackageName string `json:"restricted_package_name,omitempty"`
|
||||
Notification *Notification `json:"notification,omitempty"`
|
||||
Data map[string]interface{} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// Validate returns an error if the message is not well-formed.
|
||||
func (msg *Message) Validate() error {
|
||||
if msg == nil {
|
||||
return ErrInvalidMessage
|
||||
}
|
||||
|
||||
// validate target identifier: `to` or `condition`, or `registration_ids`
|
||||
opCnt := strings.Count(msg.Condition, "&&") + strings.Count(msg.Condition, "||")
|
||||
if msg.To == "" && (msg.Condition == "" || opCnt > 2) && len(msg.RegistrationIDs) == 0 {
|
||||
return ErrInvalidTarget
|
||||
}
|
||||
|
||||
if len(msg.RegistrationIDs) > 1000 {
|
||||
return ErrToManyRegIDs
|
||||
}
|
||||
|
||||
if msg.TimeToLive != nil && *msg.TimeToLive > uint(2419200) {
|
||||
return ErrInvalidTimeToLive
|
||||
}
|
||||
return nil
|
||||
}
|
||||
28
vendor/github.com/appleboy/go-fcm/option.go
generated
vendored
Normal file
28
vendor/github.com/appleboy/go-fcm/option.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
package fcm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Option configurates Client with defined option.
|
||||
type Option func(*Client) error
|
||||
|
||||
// WithEndpoint returns Option to configure FCM Endpoint.
|
||||
func WithEndpoint(endpoint string) Option {
|
||||
return func(c *Client) error {
|
||||
if endpoint == "" {
|
||||
return errors.New("invalid endpoint")
|
||||
}
|
||||
c.endpoint = endpoint
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithHTTPClient returns Option to configure HTTP Client.
|
||||
func WithHTTPClient(httpClient *http.Client) Option {
|
||||
return func(c *Client) error {
|
||||
c.client = httpClient
|
||||
return nil
|
||||
}
|
||||
}
|
||||
147
vendor/github.com/appleboy/go-fcm/response.go
generated
vendored
Normal file
147
vendor/github.com/appleboy/go-fcm/response.go
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
package fcm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrMissingRegistration occurs if registration token is not set.
|
||||
ErrMissingRegistration = errors.New("missing registration token")
|
||||
|
||||
// ErrInvalidRegistration occurs if registration token is invalid.
|
||||
ErrInvalidRegistration = errors.New("invalid registration token")
|
||||
|
||||
// ErrNotRegistered occurs when application was deleted from device and
|
||||
// token is not registered in FCM.
|
||||
ErrNotRegistered = errors.New("unregistered device")
|
||||
|
||||
// ErrInvalidPackageName occurs if package name in message is invalid.
|
||||
ErrInvalidPackageName = errors.New("invalid package name")
|
||||
|
||||
// ErrMismatchSenderID occurs when application has a new registration token.
|
||||
ErrMismatchSenderID = errors.New("mismatched sender id")
|
||||
|
||||
// ErrMessageTooBig occurs when message is too big.
|
||||
ErrMessageTooBig = errors.New("message is too big")
|
||||
|
||||
// ErrInvalidDataKey occurs if data key is invalid.
|
||||
ErrInvalidDataKey = errors.New("invalid data key")
|
||||
|
||||
// ErrInvalidTTL occurs when message has invalid TTL.
|
||||
ErrInvalidTTL = errors.New("invalid time to live")
|
||||
|
||||
// ErrUnavailable occurs when FCM service is unavailable. It makes sense
|
||||
// to retry after this error.
|
||||
ErrUnavailable = connectionError("timeout")
|
||||
|
||||
// ErrInternalServerError is internal FCM error. It makes sense to retry
|
||||
// after this error.
|
||||
ErrInternalServerError = serverError("internal server error")
|
||||
|
||||
// ErrDeviceMessageRateExceeded occurs when client sent to many requests to
|
||||
// the device.
|
||||
ErrDeviceMessageRateExceeded = errors.New("device message rate exceeded")
|
||||
|
||||
// ErrTopicsMessageRateExceeded occurs when client sent to many requests to
|
||||
// the topics.
|
||||
ErrTopicsMessageRateExceeded = errors.New("topics message rate exceeded")
|
||||
)
|
||||
|
||||
var (
|
||||
errMap = map[string]error{
|
||||
"MissingRegistration": ErrMissingRegistration,
|
||||
"InvalidRegistration": ErrInvalidRegistration,
|
||||
"NotRegistered": ErrNotRegistered,
|
||||
"InvalidPackageName": ErrInvalidPackageName,
|
||||
"MismatchSenderId": ErrMismatchSenderID,
|
||||
"MessageTooBig": ErrMessageTooBig,
|
||||
"InvalidDataKey": ErrInvalidDataKey,
|
||||
"InvalidTtl": ErrInvalidTTL,
|
||||
"Unavailable": ErrUnavailable,
|
||||
"InternalServerError": ErrInternalServerError,
|
||||
"DeviceMessageRateExceeded": ErrDeviceMessageRateExceeded,
|
||||
"TopicsMessageRateExceeded": ErrTopicsMessageRateExceeded,
|
||||
}
|
||||
)
|
||||
|
||||
// connectionError represents connection errors such as timeout error, etc.
|
||||
// Implements `net.Error` interface.
|
||||
type connectionError string
|
||||
|
||||
func (err connectionError) Error() string {
|
||||
return string(err)
|
||||
}
|
||||
|
||||
func (err connectionError) Temporary() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (err connectionError) Timeout() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// serverError represents internal server errors.
|
||||
// Implements `net.Error` interface.
|
||||
type serverError string
|
||||
|
||||
func (err serverError) Error() string {
|
||||
return string(err)
|
||||
}
|
||||
|
||||
func (serverError) Temporary() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (serverError) Timeout() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Response represents the FCM server's response to the application
|
||||
// server's sent message.
|
||||
type Response struct {
|
||||
MulticastID int64 `json:"multicast_id"`
|
||||
Success int `json:"success"`
|
||||
Failure int `json:"failure"`
|
||||
CanonicalIDs int `json:"canonical_ids"`
|
||||
Results []Result `json:"results"`
|
||||
}
|
||||
|
||||
// Result represents the status of a processed message.
|
||||
type Result struct {
|
||||
MessageID string `json:"message_id"`
|
||||
RegistrationID string `json:"registration_id"`
|
||||
Error error `json:"error"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler interface.
|
||||
func (r *Result) UnmarshalJSON(data []byte) error {
|
||||
var result struct {
|
||||
MessageID string `json:"message_id"`
|
||||
RegistrationID string `json:"registration_id"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &result); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.MessageID = result.MessageID
|
||||
r.RegistrationID = result.RegistrationID
|
||||
r.Error = errMap[result.Error]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unregistered checks if the device token is unregistered,
|
||||
// according to response from FCM server. Useful to determine
|
||||
// if app is uninstalled.
|
||||
func (r Result) Unregistered() bool {
|
||||
switch r.Error {
|
||||
case ErrNotRegistered, ErrMismatchSenderID, ErrMissingRegistration, ErrInvalidRegistration:
|
||||
return true
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
34
vendor/github.com/appleboy/go-fcm/retry.go
generated
vendored
Normal file
34
vendor/github.com/appleboy/go-fcm/retry.go
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
package fcm
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
minBackoff = 100 * time.Millisecond
|
||||
maxBackoff = 1 * time.Minute
|
||||
factor = 2.7
|
||||
)
|
||||
|
||||
func retry(fn func() error, attempts int) error {
|
||||
var attempt int
|
||||
for {
|
||||
err := fn()
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if tErr, ok := err.(net.Error); !ok || !tErr.Temporary() {
|
||||
return err
|
||||
}
|
||||
|
||||
attempt++
|
||||
backoff := minBackoff * time.Duration(attempt*attempt)
|
||||
if attempt > attempts || backoff > maxBackoff {
|
||||
return err
|
||||
}
|
||||
|
||||
time.Sleep(backoff)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user