2018-04-30 15:57:11 +00:00
|
|
|
package sdk
|
|
|
|
|
|
|
|
import (
|
2018-04-30 17:07:36 +00:00
|
|
|
"encoding/hex"
|
2018-04-30 15:57:11 +00:00
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
2018-04-30 17:07:36 +00:00
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/crypto/sha3"
|
|
|
|
)
|
|
|
|
|
2018-05-03 13:44:28 +00:00
|
|
|
const (
|
2018-04-30 17:07:36 +00:00
|
|
|
// NewContactKeyType message type for newContactKeyFormat
|
|
|
|
NewContactKeyType = "~#c1"
|
|
|
|
// ContactRequestType message type for contactRequestFormat
|
|
|
|
ContactRequestType = "~#c2"
|
|
|
|
// ConfirmedContactRequestType message type for confirmedContactRequestFormat
|
|
|
|
ConfirmedContactRequestType = "~#c3"
|
|
|
|
// StandardMessageType message type for StandardMessageFormat
|
|
|
|
StandardMessageType = "~#c4"
|
|
|
|
// SeenType message type for SeentType
|
|
|
|
SeenType = "~#c5"
|
|
|
|
// ContactUpdateType message type for contactUpdateMsg
|
|
|
|
ContactUpdateType = "~#c6"
|
2018-05-03 13:24:38 +00:00
|
|
|
// PNBroadcastAvailabilityType message type for push notification broadcast
|
|
|
|
// availability
|
|
|
|
PNBroadcastAvailabilityType = "~#c90"
|
|
|
|
// PNRegistrationType message type for sending a registration request to
|
|
|
|
// a push notification server
|
|
|
|
PNRegistrationType = "~#c91"
|
|
|
|
// PNRegistrationConfirmationType message type to allow a push notification
|
|
|
|
// server confirm a registration
|
2018-05-03 13:44:28 +00:00
|
|
|
PNRegistrationConfirmationType = "~#c92"
|
2018-04-30 15:57:11 +00:00
|
|
|
)
|
|
|
|
|
2018-04-30 17:07:36 +00:00
|
|
|
// supportedMessage check if the message type is supported
|
|
|
|
func supportedMessage(msgType string) bool {
|
|
|
|
_, ok := map[string]bool{
|
2018-05-03 13:24:38 +00:00
|
|
|
NewContactKeyType: true,
|
|
|
|
ContactRequestType: true,
|
|
|
|
ConfirmedContactRequestType: true,
|
|
|
|
StandardMessageType: true,
|
|
|
|
SeenType: true,
|
|
|
|
ContactUpdateType: true,
|
|
|
|
PNBroadcastAvailabilityType: true,
|
|
|
|
PNRegistrationType: true,
|
|
|
|
PNRegistrationConfirmationType: true,
|
2018-04-30 17:07:36 +00:00
|
|
|
}[msgType]
|
|
|
|
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
2018-04-30 15:57:11 +00:00
|
|
|
// Msg is a structure used by Subscribers and Publish().
|
|
|
|
type Msg struct {
|
2018-05-07 11:33:47 +00:00
|
|
|
From string `json:"from"`
|
2018-05-11 05:55:55 +00:00
|
|
|
PubKey string `json:"sig"`
|
2018-05-07 11:33:47 +00:00
|
|
|
ChannelName string `json:"channel"`
|
|
|
|
Channel *Channel `json:"-"`
|
|
|
|
Raw string `json:"-"`
|
|
|
|
Type string `json:"-"`
|
2018-05-03 14:59:27 +00:00
|
|
|
Properties interface{}
|
2018-04-30 15:57:11 +00:00
|
|
|
}
|
|
|
|
|
2018-04-30 17:07:36 +00:00
|
|
|
// ID gets the message id
|
|
|
|
func (m *Msg) ID() string {
|
|
|
|
return fmt.Sprintf("%X", sha3.Sum256([]byte(m.Raw)))
|
|
|
|
}
|
|
|
|
|
|
|
|
func rawrChatMessage(raw string) string {
|
|
|
|
bytes := []byte(raw)
|
|
|
|
|
|
|
|
return fmt.Sprintf("0x%s", hex.EncodeToString(bytes))
|
|
|
|
}
|
|
|
|
|
|
|
|
func unrawrChatMessage(message string) ([]byte, error) {
|
|
|
|
return hex.DecodeString(message[2:])
|
|
|
|
}
|
|
|
|
|
2018-05-03 13:24:38 +00:00
|
|
|
func messageFromEnvelope(u interface{}) (msg *Msg, err error) {
|
|
|
|
payload := u.(map[string]interface{})["payload"]
|
2018-05-11 05:55:55 +00:00
|
|
|
msg, err = messageFromPayload(payload.(string))
|
|
|
|
if pubkey, ok := u.(map[string]interface{})["sig"]; ok {
|
|
|
|
msg.PubKey = pubkey.(string)
|
|
|
|
}
|
|
|
|
return
|
2018-05-03 13:24:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func messageFromPayload(payload string) (*Msg, error) {
|
2018-05-01 07:46:34 +00:00
|
|
|
var msg []interface{}
|
|
|
|
|
|
|
|
rawMsg, err := unrawrChatMessage(payload)
|
2018-04-30 15:57:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2018-05-01 07:46:34 +00:00
|
|
|
if err = json.Unmarshal(rawMsg, &msg); err != nil {
|
2018-04-30 17:07:36 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-05-01 07:46:34 +00:00
|
|
|
if len(msg) < 1 {
|
|
|
|
return nil, errors.New("unknown message format")
|
2018-04-30 15:57:11 +00:00
|
|
|
}
|
2018-05-01 07:46:34 +00:00
|
|
|
|
|
|
|
msgType := msg[0].(string)
|
|
|
|
if !supportedMessage(msgType) {
|
2018-04-30 15:57:11 +00:00
|
|
|
return nil, errors.New("unsupported message type")
|
|
|
|
}
|
2018-05-01 07:46:34 +00:00
|
|
|
|
2018-05-03 14:59:27 +00:00
|
|
|
message := Msg{
|
|
|
|
From: "TODO : someone",
|
|
|
|
Type: msgType,
|
|
|
|
Raw: string(rawMsg),
|
|
|
|
}
|
|
|
|
|
2018-05-01 07:46:34 +00:00
|
|
|
properties := msg[1].([]interface{})
|
2018-05-03 14:59:27 +00:00
|
|
|
switch msgType {
|
|
|
|
case NewContactKeyType:
|
|
|
|
message.Properties = newContactKeyMsgFromProperties(properties)
|
|
|
|
case ContactRequestType:
|
|
|
|
message.Properties = contactMsgFromProperties(properties)
|
|
|
|
case ConfirmedContactRequestType:
|
|
|
|
message.Properties = confirmedContactMsgFromProperties(properties)
|
|
|
|
case StandardMessageType:
|
|
|
|
message.Properties = publishMsgFromProperties(properties)
|
|
|
|
case SeenType:
|
|
|
|
message.Properties = seenMsgFromProperties(properties)
|
|
|
|
case ContactUpdateType:
|
|
|
|
message.Properties = contactUpdateMsgFromProperties(properties)
|
|
|
|
case PNBroadcastAvailabilityType:
|
|
|
|
message.Properties = pnBroadcastAvailabilityMsgFromProperties(properties)
|
|
|
|
case PNRegistrationType:
|
|
|
|
message.Properties = pnRegistrationMsgFromProperties(properties)
|
|
|
|
case PNRegistrationConfirmationType:
|
2018-05-08 10:44:06 +00:00
|
|
|
message.Properties = pnRegistrationConfirmationMsgFromProperties(properties)
|
2018-05-03 14:59:27 +00:00
|
|
|
default:
|
|
|
|
return nil, errors.New("unsupported message type")
|
|
|
|
}
|
2018-04-30 15:57:11 +00:00
|
|
|
|
2018-05-03 14:59:27 +00:00
|
|
|
return &message, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// PublishMsg representation of a StandardMessageType
|
|
|
|
type PublishMsg struct {
|
|
|
|
Text string
|
|
|
|
MimeType string
|
|
|
|
Visibility string
|
2018-05-03 15:12:04 +00:00
|
|
|
ClockValue float64
|
|
|
|
Timestamp float64
|
2018-07-16 13:01:00 +00:00
|
|
|
Address string
|
2018-05-03 14:59:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func publishMsgFromProperties(properties []interface{}) *PublishMsg {
|
|
|
|
return &PublishMsg{
|
|
|
|
Text: properties[0].(string),
|
|
|
|
MimeType: properties[1].(string),
|
|
|
|
Visibility: properties[2].(string),
|
2018-05-03 15:12:04 +00:00
|
|
|
ClockValue: properties[3].(float64),
|
|
|
|
Timestamp: properties[4].(float64),
|
2018-05-03 13:44:28 +00:00
|
|
|
}
|
2018-05-03 14:59:27 +00:00
|
|
|
}
|
2018-05-03 13:44:28 +00:00
|
|
|
|
2018-05-03 15:12:04 +00:00
|
|
|
// ContactMsg parsed struct for ContactRequestType
|
2018-05-03 14:59:27 +00:00
|
|
|
type ContactMsg struct {
|
|
|
|
Name string
|
|
|
|
Image string
|
|
|
|
Address string
|
|
|
|
FCMToken string // This will be deprecated
|
|
|
|
}
|
|
|
|
|
|
|
|
func contactMsgFromProperties(properties []interface{}) *ContactMsg {
|
2018-06-12 11:02:58 +00:00
|
|
|
crProperties := properties[1].([]interface{})
|
2018-05-03 14:59:27 +00:00
|
|
|
|
|
|
|
return &ContactMsg{
|
|
|
|
Name: crProperties[0].(string),
|
|
|
|
Image: crProperties[1].(string),
|
|
|
|
Address: crProperties[2].(string),
|
|
|
|
FCMToken: crProperties[3].(string),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-03 15:12:04 +00:00
|
|
|
// NewContactKeyMsg parsed struct for NewContactKeyType
|
2018-05-03 14:59:27 +00:00
|
|
|
type NewContactKeyMsg struct {
|
|
|
|
Address string
|
|
|
|
Topic string
|
|
|
|
Contact *ContactMsg
|
|
|
|
}
|
|
|
|
|
|
|
|
func newContactKeyMsgFromProperties(properties []interface{}) *NewContactKeyMsg {
|
|
|
|
crProperties := properties[2].([]interface{})
|
|
|
|
|
|
|
|
return &NewContactKeyMsg{
|
|
|
|
Address: properties[0].(string),
|
|
|
|
Topic: properties[1].(string),
|
|
|
|
Contact: contactMsgFromProperties(crProperties),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-03 15:12:04 +00:00
|
|
|
// ConfirmedContactMsg parsed struct for ConfirmedContactRequestType
|
2018-05-03 14:59:27 +00:00
|
|
|
type ConfirmedContactMsg struct {
|
|
|
|
Name string
|
|
|
|
Image string
|
|
|
|
Address string
|
|
|
|
FCMToken string // This will be deprecated
|
|
|
|
}
|
|
|
|
|
|
|
|
func confirmedContactMsgFromProperties(properties []interface{}) *ConfirmedContactMsg {
|
|
|
|
return &ConfirmedContactMsg{
|
|
|
|
Name: properties[0].(string),
|
|
|
|
Image: properties[1].(string),
|
|
|
|
Address: properties[2].(string),
|
|
|
|
FCMToken: properties[3].(string),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-03 15:12:04 +00:00
|
|
|
// SeenMsg parsed struct for SeenType
|
2018-05-03 14:59:27 +00:00
|
|
|
type SeenMsg struct {
|
|
|
|
ID1 string
|
|
|
|
ID2 string
|
|
|
|
}
|
|
|
|
|
|
|
|
func seenMsgFromProperties(properties []interface{}) *SeenMsg {
|
|
|
|
return &SeenMsg{
|
|
|
|
ID1: properties[0].(string),
|
|
|
|
ID2: properties[1].(string),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-03 15:12:04 +00:00
|
|
|
// ContactUpdateMsg parsed struct for ContactUpdateType
|
2018-05-03 14:59:27 +00:00
|
|
|
type ContactUpdateMsg struct {
|
|
|
|
Name string
|
|
|
|
Image string
|
|
|
|
}
|
|
|
|
|
|
|
|
func contactUpdateMsgFromProperties(properties []interface{}) *ContactUpdateMsg {
|
|
|
|
return &ContactUpdateMsg{
|
|
|
|
Name: properties[0].(string),
|
|
|
|
Image: properties[1].(string),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-03 15:12:04 +00:00
|
|
|
// PNBroadcastAvailabilityMsg parsed struct for PNBroadcastAvailabilityType
|
2018-05-03 14:59:27 +00:00
|
|
|
type PNBroadcastAvailabilityMsg struct {
|
|
|
|
Pubkey string
|
|
|
|
}
|
|
|
|
|
|
|
|
func pnBroadcastAvailabilityMsgFromProperties(properties []interface{}) *PNBroadcastAvailabilityMsg {
|
|
|
|
return &PNBroadcastAvailabilityMsg{
|
|
|
|
Pubkey: properties[0].(string),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-03 15:12:04 +00:00
|
|
|
// PNRegistrationMsg parsed struct for PNRegistrationType
|
2018-05-03 14:59:27 +00:00
|
|
|
type PNRegistrationMsg struct {
|
|
|
|
Symkey string
|
|
|
|
Topic string
|
|
|
|
DeviceToken string
|
2018-05-08 10:44:06 +00:00
|
|
|
SlotAvailability float64
|
2018-05-03 14:59:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func pnRegistrationMsgFromProperties(properties []interface{}) *PNRegistrationMsg {
|
|
|
|
return &PNRegistrationMsg{
|
|
|
|
Symkey: properties[0].(string),
|
|
|
|
Topic: properties[1].(string),
|
|
|
|
DeviceToken: properties[2].(string),
|
2018-05-08 10:44:06 +00:00
|
|
|
SlotAvailability: properties[3].(float64),
|
2018-05-03 14:59:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-03 15:12:04 +00:00
|
|
|
// PNRegistrationConfirmationMsg parsed struct for PNRegistrationConfirmationType
|
2018-05-03 14:59:27 +00:00
|
|
|
type PNRegistrationConfirmationMsg struct {
|
|
|
|
Pubkey string
|
|
|
|
}
|
|
|
|
|
|
|
|
func pnRegistrationConfirmationMsgFromProperties(properties []interface{}) *PNRegistrationConfirmationMsg {
|
|
|
|
return &PNRegistrationConfirmationMsg{
|
|
|
|
Pubkey: properties[0].(string),
|
|
|
|
}
|
2018-04-30 15:57:11 +00:00
|
|
|
}
|