2019-11-21 16:19:22 +00:00
|
|
|
package protocol
|
2019-07-17 22:25:42 +00:00
|
|
|
|
|
|
|
import (
|
2019-09-26 07:01:17 +00:00
|
|
|
"container/list"
|
2019-07-17 22:25:42 +00:00
|
|
|
"errors"
|
|
|
|
"io"
|
|
|
|
"reflect"
|
|
|
|
|
|
|
|
"github.com/russolsen/transit"
|
|
|
|
)
|
|
|
|
|
2019-09-26 07:01:17 +00:00
|
|
|
var (
|
|
|
|
pairMessageType = reflect.TypeOf(PairMessage{})
|
|
|
|
membershipUpdateType = reflect.TypeOf(MembershipUpdateMessage{})
|
|
|
|
|
|
|
|
defaultMessageValueEncoder = &messageValueEncoder{}
|
|
|
|
)
|
|
|
|
|
2019-07-17 22:25:42 +00:00
|
|
|
// NewMessageEncoder returns a new Transit encoder
|
|
|
|
// that can encode Message values.
|
|
|
|
// More about Transit: https://github.com/cognitect/transit-format
|
|
|
|
func NewMessageEncoder(w io.Writer) *transit.Encoder {
|
|
|
|
encoder := transit.NewEncoder(w, false)
|
|
|
|
encoder.AddHandler(pairMessageType, defaultMessageValueEncoder)
|
2019-09-26 07:01:17 +00:00
|
|
|
encoder.AddHandler(membershipUpdateType, defaultMessageValueEncoder)
|
2019-07-17 22:25:42 +00:00
|
|
|
return encoder
|
|
|
|
}
|
|
|
|
|
|
|
|
type messageValueEncoder struct{}
|
|
|
|
|
|
|
|
func (messageValueEncoder) IsStringable(reflect.Value) bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (messageValueEncoder) Encode(e transit.Encoder, value reflect.Value, asString bool) error {
|
|
|
|
switch message := value.Interface().(type) {
|
|
|
|
case PairMessage:
|
|
|
|
taggedValue := transit.TaggedValue{
|
|
|
|
Tag: pairMessageTag,
|
|
|
|
Value: []interface{}{
|
|
|
|
message.InstallationID,
|
|
|
|
message.DeviceType,
|
|
|
|
message.Name,
|
|
|
|
message.FCMToken,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
return e.EncodeInterface(taggedValue, false)
|
2019-09-26 07:01:17 +00:00
|
|
|
case MembershipUpdateMessage:
|
|
|
|
updatesList := list.New()
|
|
|
|
for _, update := range message.Updates {
|
|
|
|
var events []interface{}
|
|
|
|
for _, event := range update.Events {
|
|
|
|
eventMap := map[interface{}]interface{}{
|
|
|
|
transit.Keyword("type"): event.Type,
|
|
|
|
transit.Keyword("clock-value"): event.ClockValue,
|
|
|
|
}
|
|
|
|
if event.Name != "" {
|
|
|
|
eventMap[transit.Keyword("name")] = event.Name
|
|
|
|
}
|
|
|
|
if event.Member != "" {
|
|
|
|
eventMap[transit.Keyword("member")] = event.Member
|
|
|
|
}
|
|
|
|
if len(event.Members) > 0 {
|
|
|
|
members := make([]interface{}, len(event.Members))
|
|
|
|
for idx, m := range event.Members {
|
|
|
|
members[idx] = m
|
|
|
|
}
|
|
|
|
eventMap[transit.Keyword("members")] = transit.NewSet(members)
|
|
|
|
}
|
|
|
|
events = append(events, eventMap)
|
|
|
|
}
|
|
|
|
|
|
|
|
element := map[interface{}]interface{}{
|
|
|
|
transit.Keyword("chat-id"): update.ChatID,
|
|
|
|
transit.Keyword("events"): events,
|
|
|
|
transit.Keyword("signature"): update.Signature,
|
|
|
|
}
|
|
|
|
updatesList.PushBack(element)
|
|
|
|
}
|
|
|
|
value := []interface{}{
|
|
|
|
message.ChatID,
|
|
|
|
updatesList,
|
|
|
|
}
|
|
|
|
taggedValue := transit.TaggedValue{
|
|
|
|
Tag: membershipUpdateTag,
|
|
|
|
Value: value,
|
|
|
|
}
|
|
|
|
return e.EncodeInterface(taggedValue, false)
|
2019-07-17 22:25:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return errors.New("unknown message type to encode")
|
|
|
|
}
|