Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to send message if recipient is offline #141

Open
jerrygzy opened this issue Oct 12, 2024 · 10 comments
Open

how to send message if recipient is offline #141

jerrygzy opened this issue Oct 12, 2024 · 10 comments

Comments

@jerrygzy
Copy link

jerrygzy commented Oct 12, 2024

Hi, I have been testing nkn-sdk-go, and got a problem of sending message to nMobile when recipient is offline.

following code is my current implementation, which only works when recipient's APP is active on screen.

file send.go

package main

import (
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"time"

	"github.com/google/uuid"
	"github.com/nknorg/nkn-sdk-go"
)

type DataMsg struct {
    ContentType string `json:"contentType"`
    ID          string `json:"id"`
    Content     string `json:"content"`
    IsPrivate   bool   `json:"isPrivate"`
    Timestamp   int64  `json:"timestamp"`
}



func main() {
	err := func() error {

		// from jerry' P40
		account, err := nkn.NewAccount(nil)
		if err != nil {
			return err
		}

		fromIdentifier := make([]byte, 8)
		_, err = rand.Read(fromIdentifier)
		if err != nil {
			return err
		}

		// fromClient, err := nkn.NewMultiClientV2(account, hex.EncodeToString(fromIdentifier), nil)
		fromClient, err := nkn.NewMultiClientV2(account, "", nil)
		if err != nil {
			return err
		}
		defer fromClient.Close()
		<-fromClient.OnConnect.C


		time.Sleep(time.Second)

		// send from 	random 
		// send to 		4e90a1235f1fda3ba5328189fdb7c225fb621afeb660b0cde3dd8575a10fecc8
		log.Println("Send message from", fromClient.Address(), "to", "4e90a1235f1fda3ba5328189fdb7c225fb621afeb660b0cde3dd8575a10fecc8")

		// msg for nmobile
		msg := DataMsg{
			ContentType: "text",
			ID:          uuid.New().String(),   // Equivalent to uuidv4() in JavaScript
			Content:     "64955",
			IsPrivate:   true,
			Timestamp:   time.Now().UnixMilli(),  // Equivalent to new Date().getTime()
		}

		// Marshal the map to JSON
		text, err := json.Marshal(msg)
		if err != nil {
			return err
		}
		log.Println(string(text))
		onReply, err := fromClient.Send(nkn.NewStringArray("4e90a1235f1fda3ba5328189fdb7c225fb621afeb660b0cde3dd8575a10fecc8"), string(text), nil)
		if err != nil {
			return err
		}
		reply := <-onReply.C
		isEncryptedStr := "unencrypted"
		if reply.Encrypted {
			isEncryptedStr = "encrypted"
		}
		timeResponse := time.Now().UnixNano() / int64(time.Millisecond)
		log.Println("Got", isEncryptedStr, "reply", "\""+string(reply.Data)+"\"", "from", reply.Src, "at", timeResponse, "ms")

		// wait to send receipt
		time.Sleep(time.Second)

		return nil
	}()
	if err != nil {
		fmt.Println(err)
	}
}

test: go run send.go

change following recipient for test.

4e90a1235f1fda3ba5328189fdb7c225fb621afeb660b0cde3dd8575a10fecc8 ( copied from nMobile )

@yilunzhang
Copy link
Member

You can pass a MessageConfig with MaxHoldingSeconds to Send, see https://pkg.go.dev/github.com/nknorg/nkn-sdk-go#MessageConfig

@jerrygzy
Copy link
Author

jerrygzy commented Oct 14, 2024

is this correct?

		// msg for nmobile
		var msg_config = nkn.MessageConfig{
			Unencrypted:       false,
			NoReply:           true,
			MaxHoldingSeconds: 600,
			MessageID:         nil,
			TxPool:            false,
			Offset:            0,
			Limit:             1000,
		}
		msg := DataMsg{
			ContentType: "text",
			ID:          uuid.New().String(),
			Content:     "64955",
			IsPrivate:   true,
			Timestamp:   time.Now().UnixMilli(),  // Equivalent to new Date().getTime()
		}


		// Marshal the map to JSON
		msg_json, err := json.Marshal(msg)
		if err != nil {
			return err
		}
		log.Println(string(msg_json))
		onReply, err := fromClient.Send(nkn.NewStringArray("4e90a1235f1fda3ba5328189fdb7c225fb621afeb660b0cde3dd8575a10fecc8"), string(msg_json), &msg_config)
		if err != nil {
			return err
		}

I am not sure about

			TxPool:            false,
			Offset:            0,
			Limit:             1000,

@yilunzhang
Copy link
Member

That's right. Actually you can simply do:

msgConfig := nkn.MessageConfig{
    MaxHoldingSeconds: 600,
}

and leave the rest fields unset, the sdk will automatically use default values for those.

@jerrygzy
Copy link
Author

jerrygzy commented Oct 14, 2024

OK, last question

I have enabled Message Notification for a Sender in recipient's nMobile, how to use sdk for sender to use that feature?

@yilunzhang
Copy link
Member

That part cannot be done by the SDK because of iOS/Android restrictions. The only way to send push notification to iOS/Android device is to get target device's push notification token, and use that token to send notification through Apple/Google push notification server. So if you want to do it, you will need to save recipient's push notification token (you will receive a NKN message when recipient enables notification for you in nMobile), and use that token to send push notification yourself.

@jerrygzy
Copy link
Author

@yilunzhang thanks for the reply, so I have tried to get the push notification token with following code,

		reply := <-onReply.C

		isEncryptedStr := "unencrypted"
		if reply.Encrypted {
			isEncryptedStr = "encrypted"
		}
		timeResponse := time.Now().UnixNano() / int64(time.Millisecond)

		log.Println("Got", isEncryptedStr, "reply", "\""+string(reply.Data)+"\"", "from", reply.Src, "at", timeResponse, "ms")

after I toggle the Message Notification switch, I did not see log.Println on terminal, how should I modify my code?

@yilunzhang
Copy link
Member

you need to make sure the address you are listening at in the sdk and the address you are talking to in nMobile are the same. Then you can try printing all messages received in sdk and see if you can receive messages when you send messages and toggle notifications in nMobile

@jerrygzy
Copy link
Author

OK, now I have got two different message type from nMobile,

type 1

"{
"id":"7d26a046-5ab0-45a5-980d-1924d5932c17",
"timestamp":1728970853153,
"deviceId":"F04CC24C-XXXX-XXXX-XXXX-5D9910C8BA2B",
"contentType":"receipt",
"targetID":"8c8af4e2-e7de-40f5-84e5-81f0967dd639"
}"

type 2

"{
"id":"6c599c63-7205-433b-906e-1c1fbdedccf1",
"timestamp":1728971167588,
"deviceId":"F04CC24C-XXXX-XXXX-XXXX-5D9910C8BA2B",
"contentType":"ping",
"content":"ping",
"options":{
    "profileVersion":"4d7a14c9-2a22-468e-9e65-d90ec642865a",
    "deviceToken":"[APNS]:7b5d97a21c94805a99afc7852514d3b34737e9eb02bb352747a14a5cfbaebc3c",
    "deviceProfile":"nMobile:312:ios:16:F04CC24C-XXXX-XXXX-XXXX-5D9910C8BA2B",
    "messageQueueIds":"6_::_0_::__::_d1c99d0e75c2817d"
    }
}"

I noticed "deviceToken":"[APNS]:7b5d97a21c94805a99afc7852514d3b34737e9eb02bb352747a14a5cfbaebc3c", which looks like push notification token for iOS device, is that correct?

and for type 1 message from nMobile, should I ignore it?

@yilunzhang
Copy link
Member

Yeah APNS is short for Apple Push Notification Service. And you can ignore messages you don't need now.

@jerrygzy
Copy link
Author

jerrygzy commented Oct 16, 2024

@yilunzhang after some further reading and research, here is what I have found.

APNS_URL:
The URL https://api.push.apple.com/3/device/ is the endpoint for sending push notifications to iOS devices. It is where your server will send HTTP requests containing the notification payload and the device token.
APNS_KEY_ID:
This is a unique identifier for the APNs Auth Key that you create in your Apple Developer account. It is required for generating a JSON Web Token (JWT), which authenticates your requests to APNs.
APNS_TEAM_ID:
The Team ID identifies your Apple Developer account and is used in conjunction with the Key ID to create the JWT. This ensures that only authorized applications can send notifications to devices.
APNS_AUTH_KEY_PATH:
This path points to the .p8 file that contains your APNs Auth Key. The key is used to sign the JWT, allowing you to authenticate with APNs securely.

Implications for 3rd Party Service Providers

If you are a third-party service provider for a chat app, these credentials are still necessary for sending push notifications on behalf of your clients (the app developers). Here’s how it typically works:

Client Configuration: Your clients (the chat app developers) must provide you with their APNS_KEY_ID, APNS_TEAM_ID, and the path to their .p8 file. They would also need to ensure that their app is configured correctly in their Apple Developer account to support push notifications.

Sending Notifications: When you receive a request to send a notification, you would use the provided credentials along with the device token of the target user (which you would have received from the client’s app) to construct and send the notification request to APNs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants