Compare commits
No commits in common. "master" and "v1.3.10" have entirely different histories.
|
@ -160,7 +160,7 @@ func makeSendResponseFromPart(part *multipart.Part) (SendResponse, error) {
|
||||||
}
|
}
|
||||||
defer response.Body.Close()
|
defer response.Body.Close()
|
||||||
|
|
||||||
body, err := io.ReadAll(response.Body)
|
body, err := ioutil.ReadAll(response.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return SendResponse{}, errors.WithStack(err)
|
return SendResponse{}, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
26
fcm.go
26
fcm.go
|
@ -15,19 +15,17 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"git.bit5.ru/backend/errors"
|
"git.bit5.ru/backend/errors"
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
|
|
||||||
"go.opentelemetry.io/otel"
|
"go.opentelemetry.io/otel"
|
||||||
"go.opentelemetry.io/otel/attribute"
|
"go.opentelemetry.io/otel/attribute"
|
||||||
"go.opentelemetry.io/otel/codes"
|
"go.opentelemetry.io/otel/codes"
|
||||||
"go.opentelemetry.io/otel/trace"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const tracerName = "git.bit5.ru/backend/fcm"
|
const tracerName = "git.bit5.ru/backend/fcm"
|
||||||
|
@ -47,7 +45,7 @@ var (
|
||||||
AuthScopes = []string{"https://www.googleapis.com/auth/firebase.messaging"}
|
AuthScopes = []string{"https://www.googleapis.com/auth/firebase.messaging"}
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeSendEndpoint(projectId string) string {
|
func MakeSendEndpoint(projectId string) string {
|
||||||
return fmt.Sprintf("https://fcm.googleapis.com/v1/projects/%s/messages:send", projectId)
|
return fmt.Sprintf("https://fcm.googleapis.com/v1/projects/%s/messages:send", projectId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +64,7 @@ type Credentials struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadCredentialsFromFile(filename string) (Credentials, error) {
|
func ReadCredentialsFromFile(filename string) (Credentials, error) {
|
||||||
data, err := os.ReadFile(filename)
|
data, err := ioutil.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Credentials{}, errors.WithStack(err)
|
return Credentials{}, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
@ -79,16 +77,20 @@ func ReadCredentialsFromFile(filename string) (Credentials, error) {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ClientConfig struct {
|
||||||
|
SendEndpoint string
|
||||||
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
sendEndpoint string
|
cfg ClientConfig
|
||||||
ts oauth2.TokenSource
|
ts oauth2.TokenSource
|
||||||
hc *http.Client
|
hc *http.Client
|
||||||
logger logr.Logger
|
logger logr.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(projectId string, ts oauth2.TokenSource, hc *http.Client, logger logr.Logger) *Client {
|
func NewClient(cfg ClientConfig, ts oauth2.TokenSource, hc *http.Client, logger logr.Logger) *Client {
|
||||||
return &Client{
|
return &Client{
|
||||||
sendEndpoint: makeSendEndpoint(projectId),
|
cfg: cfg,
|
||||||
ts: ts,
|
ts: ts,
|
||||||
hc: hc,
|
hc: hc,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
@ -163,11 +165,7 @@ func (c *Client) Validate(ctx context.Context, message Message) (string, error)
|
||||||
|
|
||||||
func (c *Client) doSendRequest(ctx context.Context, req SendRequest, loggerEnabled bool) (SendResponse, error) {
|
func (c *Client) doSendRequest(ctx context.Context, req SendRequest, loggerEnabled bool) (SendResponse, error) {
|
||||||
|
|
||||||
spanAttrs := trace.WithAttributes(
|
_, span := tracer.Start(ctx, "Client.doSendRequest")
|
||||||
attribute.String("token", req.Message.Token),
|
|
||||||
)
|
|
||||||
|
|
||||||
_, span := tracer.Start(ctx, "Client.doSendRequest", spanAttrs)
|
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
accessToken, err := c.ts.Token()
|
accessToken, err := c.ts.Token()
|
||||||
|
@ -190,7 +188,7 @@ func (c *Client) doSendRequest(ctx context.Context, req SendRequest, loggerEnabl
|
||||||
c.logger.Info("sending", "message", data)
|
c.logger.Info("sending", "message", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
request, err := http.NewRequest(http.MethodPost, c.sendEndpoint, bytes.NewReader(data))
|
request, err := http.NewRequest(http.MethodPost, c.cfg.SendEndpoint, bytes.NewReader(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
span.SetStatus(codes.Error, err.Error())
|
span.SetStatus(codes.Error, err.Error())
|
||||||
span.RecordError(err)
|
span.RecordError(err)
|
||||||
|
|
10
message.go
10
message.go
|
@ -1,14 +1,9 @@
|
||||||
package fcm
|
package fcm
|
||||||
|
|
||||||
// Message to send by Firebase Cloud Messaging Service.
|
|
||||||
// https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#resource:-message
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
// Union field target can be only one of the following:
|
|
||||||
Token string `json:"token,omitempty"`
|
Token string `json:"token,omitempty"`
|
||||||
Topic string `json:"topic,omitempty"`
|
Topic string `json:"topic,omitempty"`
|
||||||
Condition string `json:"condition,omitempty"`
|
Condition string `json:"condition,omitempty"`
|
||||||
// End of list of possible types for union field target.
|
|
||||||
|
|
||||||
Data map[string]string `json:"data,omitempty"`
|
Data map[string]string `json:"data,omitempty"`
|
||||||
Notification *Notification `json:"notification,omitempty"`
|
Notification *Notification `json:"notification,omitempty"`
|
||||||
FcmOptions *FcmOptions `json:"fcm_options,omitempty"`
|
FcmOptions *FcmOptions `json:"fcm_options,omitempty"`
|
||||||
|
@ -18,7 +13,6 @@ type Message struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Basic notification template to use across all platforms.
|
// Basic notification template to use across all platforms.
|
||||||
// https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#notification
|
|
||||||
type Notification struct {
|
type Notification struct {
|
||||||
Title string `json:"title,omitempty"`
|
Title string `json:"title,omitempty"`
|
||||||
Body string `json:"body,omitempty"`
|
Body string `json:"body,omitempty"`
|
||||||
|
@ -176,8 +170,8 @@ type ApnsPayload struct {
|
||||||
Aps ApnsPayloadKeys `json:"aps"`
|
Aps ApnsPayloadKeys `json:"aps"`
|
||||||
|
|
||||||
// TODO: add support for custom keys
|
// TODO: add support for custom keys
|
||||||
// https://developer.apple.com/documentation/usernotifications/generating-a-remote-notification
|
// https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification
|
||||||
customKeys map[string]any
|
customKeys map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApnsPayloadKeys struct {
|
type ApnsPayloadKeys struct {
|
||||||
|
|
Loading…
Reference in New Issue