Add `SendDataNotification` method (#1352)
This commit is contained in:
parent
aa09d854ca
commit
55b3f31318
|
@ -2,12 +2,12 @@
|
||||||
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
digest = "1:ab480b4ff653dc950445e4ac6747c2a063f3dee7b533f68d4314267ce0fd9005"
|
||||||
digest = "1:5805073c158189c2af2f776b590fc9b88bcc68f2b983842adb08333dbd3c9ae7"
|
|
||||||
name = "github.com/NaySoftware/go-fcm"
|
name = "github.com/NaySoftware/go-fcm"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "NUT"
|
pruneopts = "NUT"
|
||||||
revision = "2a6c4f48b49f0d5dbfe621589da4c5405157d7c9"
|
revision = "024ca6a2c5444c93980f558f91c35a2defebd362"
|
||||||
|
source = "github.com/status-im/go-fcm"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
|
|
@ -35,6 +35,11 @@
|
||||||
name = "github.com/golang/protobuf"
|
name = "github.com/golang/protobuf"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/NaySoftware/go-fcm"
|
||||||
|
revision = "024ca6a2c5444c93980f558f91c35a2defebd362"
|
||||||
|
source = "github.com/status-im/go-fcm"
|
||||||
|
|
||||||
# * * * * * `go-ethereum` dependencies * * * * *
|
# * * * * * `go-ethereum` dependencies * * * * *
|
||||||
# Pinned down SHAs from `go-ethereum/vendor/vendor.json`
|
# Pinned down SHAs from `go-ethereum/vendor/vendor.json`
|
||||||
# When upgrading upstream, upgrade these values too.
|
# When upgrading upstream, upgrade these values too.
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
fcmlib "github.com/NaySoftware/go-fcm"
|
|
||||||
gethcommon "github.com/ethereum/go-ethereum/common"
|
gethcommon "github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
@ -464,11 +463,23 @@ func (b *StatusBackend) SelectAccount(walletAddress, chatAddress, password strin
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotifyUsers sends push notifications to users.
|
// SendDataNotification sends data push notifications to users.
|
||||||
func (b *StatusBackend) NotifyUsers(message string, payload fcmlib.NotificationPayload, tokens ...string) error {
|
// dataPayloadJSON is a JSON string that looks like this:
|
||||||
err := b.newNotification().Send(message, payload, tokens...)
|
// {
|
||||||
|
// "data": {
|
||||||
|
// "msg-v2": {
|
||||||
|
// "from": "0x2cea3bd5", // hash of sender (first 10 characters/4 bytes of sha3 hash)
|
||||||
|
// "to": "0xb1f89744", // hash of recipient (first 10 characters/4 bytes of sha3 hash)
|
||||||
|
// "id": "0x872653ad", // message ID hash (first 10 characters/4 bytes of sha3 hash)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
func (b *StatusBackend) SendDataNotification(dataPayloadJSON string, tokens ...string) error {
|
||||||
|
log.Debug("sending data push notification")
|
||||||
|
|
||||||
|
err := b.newNotification().Send(dataPayloadJSON, tokens...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.log.Error("Notify failed", "error", err)
|
b.log.Error("SendDataNotification failed", "dataPayloadJSON", dataPayloadJSON, "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/NaySoftware/go-fcm"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/status-im/status-go/api"
|
"github.com/status-im/status-go/api"
|
||||||
"github.com/status-im/status-go/logutils"
|
"github.com/status-im/status-go/logutils"
|
||||||
|
@ -429,9 +428,19 @@ func makeJSONResponse(err error) *C.char {
|
||||||
return C.CString(string(outBytes))
|
return C.CString(string(outBytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotifyUsers sends push notifications by given tokens.
|
// SendDataNotification sends push notifications by given tokens.
|
||||||
//export NotifyUsers
|
// dataPayloadJSON is a JSON string that looks like this:
|
||||||
func NotifyUsers(message, payloadJSON, tokensArray *C.char) (outCBytes *C.char) {
|
// {
|
||||||
|
// "data": {
|
||||||
|
// "msg-v2": {
|
||||||
|
// "from": "0x2cea3bd5", // hash of sender (first 10 characters/4 bytes of sha3 hash)
|
||||||
|
// "to": "0xb1f89744", // hash of recipient (first 10 characters/4 bytes of sha3 hash)
|
||||||
|
// "id": "0x872653ad", // message ID hash (first 10 characters/4 bytes of sha3 hash)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//export SendDataNotification
|
||||||
|
func SendDataNotification(dataPayloadJSON, tokensArray *C.char) (outCBytes *C.char) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
outBytes []byte
|
outBytes []byte
|
||||||
|
@ -439,14 +448,14 @@ func NotifyUsers(message, payloadJSON, tokensArray *C.char) (outCBytes *C.char)
|
||||||
errString := ""
|
errString := ""
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
out := NotifyResult{
|
out := SendDataNotificationResult{
|
||||||
Status: err == nil,
|
Status: err == nil,
|
||||||
Error: errString,
|
Error: errString,
|
||||||
}
|
}
|
||||||
|
|
||||||
outBytes, err = json.Marshal(out)
|
outBytes, err = json.Marshal(out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed to marshal Notify output", "error", err)
|
logger.Error("failed to marshal SendDataNotification output", "error", err)
|
||||||
outCBytes = makeJSONResponse(err)
|
outCBytes = makeJSONResponse(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -460,14 +469,7 @@ func NotifyUsers(message, payloadJSON, tokensArray *C.char) (outCBytes *C.char)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var payload fcm.NotificationPayload
|
err = statusBackend.SendDataNotification(C.GoString(dataPayloadJSON), tokens...)
|
||||||
err = json.Unmarshal([]byte(C.GoString(payloadJSON)), &payload)
|
|
||||||
if err != nil {
|
|
||||||
errString = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = statusBackend.NotifyUsers(C.GoString(message), payload, tokens...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errString = err.Error()
|
errString = err.Error()
|
||||||
return
|
return
|
||||||
|
|
|
@ -74,8 +74,8 @@ type AccountInfo struct {
|
||||||
Error string `json:"error"`
|
Error string `json:"error"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotifyResult is a JSON returned from notify message.
|
// SendDataNotificationResult is a JSON returned from notify message.
|
||||||
type NotifyResult struct {
|
type SendDataNotificationResult struct {
|
||||||
Status bool `json:"status"`
|
Status bool `json:"status"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,5 +8,4 @@ import (
|
||||||
type FirebaseClient interface {
|
type FirebaseClient interface {
|
||||||
NewFcmRegIdsMsg(tokens []string, body interface{}) *gofcm.FcmClient
|
NewFcmRegIdsMsg(tokens []string, body interface{}) *gofcm.FcmClient
|
||||||
Send() (*gofcm.FcmResponseStatus, error)
|
Send() (*gofcm.FcmResponseStatus, error)
|
||||||
SetNotificationPayload(payload *gofcm.NotificationPayload) *gofcm.FcmClient
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ func (m *MockFirebaseClient) EXPECT() *MockFirebaseClientMockRecorder {
|
||||||
|
|
||||||
// NewFcmRegIdsMsg mocks base method
|
// NewFcmRegIdsMsg mocks base method
|
||||||
func (m *MockFirebaseClient) NewFcmRegIdsMsg(tokens []string, body interface{}) *go_fcm.FcmClient {
|
func (m *MockFirebaseClient) NewFcmRegIdsMsg(tokens []string, body interface{}) *go_fcm.FcmClient {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "NewFcmRegIdsMsg", tokens, body)
|
ret := m.ctrl.Call(m, "NewFcmRegIdsMsg", tokens, body)
|
||||||
ret0, _ := ret[0].(*go_fcm.FcmClient)
|
ret0, _ := ret[0].(*go_fcm.FcmClient)
|
||||||
return ret0
|
return ret0
|
||||||
|
@ -48,6 +49,7 @@ func (mr *MockFirebaseClientMockRecorder) NewFcmRegIdsMsg(tokens, body interface
|
||||||
|
|
||||||
// Send mocks base method
|
// Send mocks base method
|
||||||
func (m *MockFirebaseClient) Send() (*go_fcm.FcmResponseStatus, error) {
|
func (m *MockFirebaseClient) Send() (*go_fcm.FcmResponseStatus, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Send")
|
ret := m.ctrl.Call(m, "Send")
|
||||||
ret0, _ := ret[0].(*go_fcm.FcmResponseStatus)
|
ret0, _ := ret[0].(*go_fcm.FcmResponseStatus)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
|
@ -59,15 +61,3 @@ func (mr *MockFirebaseClientMockRecorder) Send() *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockFirebaseClient)(nil).Send))
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockFirebaseClient)(nil).Send))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNotificationPayload mocks base method
|
|
||||||
func (m *MockFirebaseClient) SetNotificationPayload(payload *go_fcm.NotificationPayload) *go_fcm.FcmClient {
|
|
||||||
ret := m.ctrl.Call(m, "SetNotificationPayload", payload)
|
|
||||||
ret0, _ := ret[0].(*go_fcm.FcmClient)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNotificationPayload indicates an expected call of SetNotificationPayload
|
|
||||||
func (mr *MockFirebaseClientMockRecorder) SetNotificationPayload(payload interface{}) *gomock.Call {
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetNotificationPayload", reflect.TypeOf((*MockFirebaseClient)(nil).SetNotificationPayload), payload)
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package fcm
|
package fcm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/NaySoftware/go-fcm"
|
"github.com/NaySoftware/go-fcm"
|
||||||
|
@ -8,7 +9,7 @@ import (
|
||||||
|
|
||||||
// Notifier manages Push Notifications.
|
// Notifier manages Push Notifications.
|
||||||
type Notifier interface {
|
type Notifier interface {
|
||||||
Send(body string, payload fcm.NotificationPayload, tokens ...string) error
|
Send(dataPayloadJSON string, tokens ...string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotificationConstructor returns constructor of configured instance Notifier interface.
|
// NotificationConstructor returns constructor of configured instance Notifier interface.
|
||||||
|
@ -25,30 +26,30 @@ func NewNotification(key string) NotificationConstructor {
|
||||||
client := fcm.NewFcmClient(key).
|
client := fcm.NewFcmClient(key).
|
||||||
SetDelayWhileIdle(true).
|
SetDelayWhileIdle(true).
|
||||||
SetContentAvailable(true).
|
SetContentAvailable(true).
|
||||||
|
SetPriority(fcm.Priority_HIGH). // Message needs to be marked as high-priority so that background task in an Android's recipient device can be invoked (https://github.com/invertase/react-native-firebase/blob/d13f0af53f1c8f20db8bc8d4b6f8c6d210e108b9/android/src/main/java/io/invertase/firebase/messaging/RNFirebaseMessagingService.java#L56)
|
||||||
SetTimeToLive(fcm.MAX_TTL)
|
SetTimeToLive(fcm.MAX_TTL)
|
||||||
|
|
||||||
return &Notification{client}
|
return &Notification{client}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send send to the tokens list.
|
// Send sends a push notification to the tokens list.
|
||||||
func (n *Notification) Send(body string, payload fcm.NotificationPayload, tokens ...string) error {
|
func (n *Notification) Send(dataPayloadJSON string, tokens ...string) error {
|
||||||
data := map[string]string{
|
var dataPayload map[string]string
|
||||||
"msg": body,
|
err := json.Unmarshal([]byte(dataPayloadJSON), &dataPayload)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if payload.Title == "" {
|
n.client.NewFcmRegIdsMsg(tokens, dataPayload)
|
||||||
payload.Title = "Status"
|
resp, err := n.client.Send()
|
||||||
}
|
if err != nil {
|
||||||
if payload.Body == "" {
|
return err
|
||||||
payload.Body = "You have a new message"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(payload.Title, payload.Body)
|
if resp != nil && !resp.Ok {
|
||||||
|
return fmt.Errorf("FCM error sending message, code=%d err=%s", resp.StatusCode, resp.Err)
|
||||||
|
}
|
||||||
|
|
||||||
n.client.NewFcmRegIdsMsg(tokens, data)
|
return nil
|
||||||
n.client.SetNotificationPayload(&payload)
|
|
||||||
_, err := n.client.Send()
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package fcm
|
package fcm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/NaySoftware/go-fcm"
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
)
|
)
|
||||||
|
@ -29,43 +29,52 @@ func (s *NotifierTestSuite) TearDownTest() {
|
||||||
s.fcmClientMockCtrl.Finish()
|
s.fcmClientMockCtrl.Finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *NotifierTestSuite) TestNotifySuccess() {
|
func (s *NotifierTestSuite) TestSendSuccess() {
|
||||||
fcmPayload := getPayload()
|
|
||||||
ids := []string{"1"}
|
ids := []string{"1"}
|
||||||
payload := fcmPayload
|
dataPayload := make(map[string]string)
|
||||||
msg := make(map[string]string)
|
dataPayload["from"] = "a"
|
||||||
body := "body1"
|
dataPayload["to"] = "b"
|
||||||
msg["msg"] = body
|
dataPayloadByteArray, err := json.Marshal(dataPayload)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
dataPayloadJSON := string(dataPayloadByteArray)
|
||||||
|
|
||||||
s.fcmClientMock.EXPECT().SetNotificationPayload(&fcmPayload).Times(1)
|
s.fcmClientMock.EXPECT().NewFcmRegIdsMsg(ids, dataPayload).Times(1)
|
||||||
s.fcmClientMock.EXPECT().NewFcmRegIdsMsg(ids, msg).Times(1)
|
|
||||||
s.fcmClientMock.EXPECT().Send().Return(nil, nil).Times(1)
|
s.fcmClientMock.EXPECT().Send().Return(nil, nil).Times(1)
|
||||||
fcmClient := Notification{s.fcmClientMock}
|
fcmClient := Notification{s.fcmClientMock}
|
||||||
|
|
||||||
err := fcmClient.Send(body, payload, ids...)
|
err = fcmClient.Send(dataPayloadJSON, ids...)
|
||||||
|
|
||||||
s.NoError(err)
|
s.NoError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *NotifierTestSuite) TestNotifyError() {
|
func (s *NotifierTestSuite) TestSendError() {
|
||||||
expectedError := errors.New("error")
|
expectedError := errors.New("error")
|
||||||
fcmPayload := getPayload()
|
ids := []string{"2"}
|
||||||
ids := []string{"1"}
|
dataPayload := make(map[string]string)
|
||||||
payload := fcmPayload
|
dataPayload["from"] = "c"
|
||||||
msg := make(map[string]string)
|
dataPayload["to"] = "d"
|
||||||
body := "body2"
|
dataPayloadByteArray, err := json.Marshal(dataPayload)
|
||||||
msg["msg"] = body
|
s.Require().NoError(err)
|
||||||
|
dataPayloadJSON := string(dataPayloadByteArray)
|
||||||
|
|
||||||
s.fcmClientMock.EXPECT().SetNotificationPayload(&fcmPayload).Times(1)
|
s.fcmClientMock.EXPECT().NewFcmRegIdsMsg(ids, dataPayload).Times(1)
|
||||||
s.fcmClientMock.EXPECT().NewFcmRegIdsMsg(ids, msg).Times(1)
|
|
||||||
s.fcmClientMock.EXPECT().Send().Return(nil, expectedError).Times(1)
|
s.fcmClientMock.EXPECT().Send().Return(nil, expectedError).Times(1)
|
||||||
fcmClient := Notification{s.fcmClientMock}
|
fcmClient := Notification{s.fcmClientMock}
|
||||||
|
|
||||||
err := fcmClient.Send(body, payload, ids...)
|
err = fcmClient.Send(dataPayloadJSON, ids...)
|
||||||
|
|
||||||
s.Equal(expectedError, err)
|
s.Equal(expectedError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPayload() fcm.NotificationPayload {
|
func (s *NotifierTestSuite) TestSendWithInvalidJSON() {
|
||||||
return fcm.NotificationPayload{Title: "Status - new message", Body: "sum"}
|
ids := []string{"3"}
|
||||||
|
dataPayloadJSON := "{a=b}"
|
||||||
|
|
||||||
|
fcmClient := Notification{s.fcmClientMock}
|
||||||
|
|
||||||
|
err := fcmClient.Send(dataPayloadJSON, ids...)
|
||||||
|
s.Require().Error(err)
|
||||||
|
|
||||||
|
_, ok := err.(*json.SyntaxError)
|
||||||
|
s.True(ok)
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ type FcmMsg struct {
|
||||||
RestrictedPackageName string `json:"restricted_package_name,omitempty"`
|
RestrictedPackageName string `json:"restricted_package_name,omitempty"`
|
||||||
DryRun bool `json:"dry_run,omitempty"`
|
DryRun bool `json:"dry_run,omitempty"`
|
||||||
Condition string `json:"condition,omitempty"`
|
Condition string `json:"condition,omitempty"`
|
||||||
|
MutableContent bool `json:"mutable_content,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FcmMsg represents fcm response message - (tokens and topics)
|
// FcmMsg represents fcm response message - (tokens and topics)
|
||||||
|
@ -179,6 +180,8 @@ func (this *FcmClient) sendOnce() (*FcmResponseStatus, error) {
|
||||||
return fcmRespStatus, err
|
return fcmRespStatus, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fcmRespStatus.Err = string(body)
|
||||||
|
|
||||||
fcmRespStatus.StatusCode = response.StatusCode
|
fcmRespStatus.StatusCode = response.StatusCode
|
||||||
|
|
||||||
fcmRespStatus.RetryAfter = response.Header.Get(retry_after_header)
|
fcmRespStatus.RetryAfter = response.Header.Get(retry_after_header)
|
||||||
|
@ -313,6 +316,19 @@ func (this *FcmClient) SetDryRun(drun bool) *FcmClient {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetMutableContent Currently for iOS 10+ devices only. On iOS,
|
||||||
|
// use this field to represent mutable-content in the APNs payload.
|
||||||
|
// When a notification is sent and this is set to true, the content
|
||||||
|
// of the notification can be modified before it is displayed,
|
||||||
|
// using a Notification Service app extension.
|
||||||
|
// This parameter will be ignored for Android and web.
|
||||||
|
func (this *FcmClient) SetMutableContent(mc bool) *FcmClient {
|
||||||
|
|
||||||
|
this.Message.MutableContent = mc
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
// PrintResults prints the FcmResponseStatus results for fast using and debugging
|
// PrintResults prints the FcmResponseStatus results for fast using and debugging
|
||||||
func (this *FcmResponseStatus) PrintResults() {
|
func (this *FcmResponseStatus) PrintResults() {
|
||||||
fmt.Println("Status Code :", this.StatusCode)
|
fmt.Println("Status Code :", this.StatusCode)
|
||||||
|
|
Loading…
Reference in New Issue