Skip to content

Commit

Permalink
Merge branch 'release/0.8.8'
Browse files Browse the repository at this point in the history
  • Loading branch information
gildas committed Sep 20, 2023
2 parents d4c581f + dda699f commit 572f13a
Show file tree
Hide file tree
Showing 9 changed files with 323 additions and 2 deletions.
2 changes: 1 addition & 1 deletion openmessaging_channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type OpenMessageChannel struct {
Type string `json:"type"` // Private, Public
MessageID string `json:"messageId,omitempty"`
Time time.Time `json:"-"`
To *OpenMessageTo `json:"to"`
To *OpenMessageTo `json:"to,omitempty"`
From *OpenMessageFrom `json:"from"`
Metadata *OpenMessageChannelMetadata `json:"metadata,omitempty"`
}
Expand Down
25 changes: 25 additions & 0 deletions openmessaging_integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,31 @@ func (integration *OpenMessagingIntegration) SendInboundReceipt(context context.
return result.ID, err
}

// SendInboundEvent sends an event from the middleware to GENESYS Cloud
//
// See https://developer.genesys.cloud/commdigital/digital/openmessaging/inboundEventMessages
func (integration *OpenMessagingIntegration) SendInboundEvents(context context.Context, from *OpenMessageFrom, attributes map[string]string, metadata map[string]string, events ...OpenMessageEvent) (id string, err error) {
if integration.ID == uuid.Nil {
return "", errors.ArgumentMissing.With("ID")
}
result := OpenMessageEvents{}
err = integration.client.Post(
integration.logger.ToContext(context),
NewURI("/conversations/messages/%s/inbound/open/event", integration.ID),
&OpenMessageEvents{
Channel: NewOpenMessageChannel(
"",
&OpenMessageTo{ID: integration.ID.String()},
from,
).WithAttributes(attributes),
Events: events,
Metadata: metadata,
},
&result,
)
return result.ID, err
}

// SendOutboundMessage sends a message from GENESYS Cloud to the middleware
//
// The message can be only text as it is sent bia the AgentLess Message API.
Expand Down
31 changes: 31 additions & 0 deletions openmessaging_message_event.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package gcloudcx

import (
"strings"

"github.com/gildas/go-core"
"github.com/gildas/go-errors"
)

type OpenMessageEvent interface {
core.TypeCarrier
}

var openMessageEventRegistry = core.TypeRegistry{}

func UnmarshalOpenMessageEvent(payload []byte) (OpenMessageEvent, error) {
message, err := openMessageEventRegistry.UnmarshalJSON(payload, "eventType")
if err == nil {
return message.(OpenMessageEvent), nil
}
if strings.HasPrefix(err.Error(), "Missing JSON Property") {
return nil, errors.JSONUnmarshalError.Wrap(errors.ArgumentMissing.With("type"))
}
if strings.HasPrefix(err.Error(), "Unsupported Type") {
return nil, errors.JSONUnmarshalError.Wrap(errors.InvalidType.With(strings.TrimSuffix(strings.TrimPrefix(err.Error(), `Unsupported Type "`), `"`)))
}
if errors.Is(err, errors.JSONUnmarshalError) {
return nil, err
}
return nil, errors.JSONUnmarshalError.Wrap(err)
}
92 changes: 92 additions & 0 deletions openmessaging_message_event_typing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package gcloudcx

import (
"encoding/json"
"time"

"github.com/gildas/go-errors"
)

// OpenMessageTypingEvent is a typing event sent or received by the Open Messaging API
type OpenMessageTypingEvent struct {
IsTyping bool `json:"-"`
Duration time.Duration `json:"-"`
}

func init() {
openMessageEventRegistry.Add(OpenMessageTypingEvent{})
}

// GetType returns the type of this event
//
// implements core.TypeCarrier
func (event OpenMessageTypingEvent) GetType() string {
return "Typing"
}

// MarshalJSON marshals this into JSON
//
// implements json.Marshaler
func (event OpenMessageTypingEvent) MarshalJSON() (data []byte, err error) {
if !event.IsTyping || event.Duration > 0 {
type TypingInfo struct {
Type string `json:"type"`
Duration int `json:"duration"`
}
newTypingInfo := func(isTyping bool, duration time.Duration) TypingInfo {
if !isTyping {
return TypingInfo{
Type: "On",
Duration: int(duration.Milliseconds()),
}
}
return TypingInfo{
Type: "Off",
Duration: int(duration.Milliseconds()),
}
}
data, err = json.Marshal(struct {
Type string `json:"eventType"`
Typing TypingInfo `json:"typing"`
}{
Type: event.GetType(),
Typing: newTypingInfo(event.IsTyping, event.Duration),
})
} else {
data, err = json.Marshal(struct {
Type string `json:"eventType"`
}{
Type: event.GetType(),
})
}
return data, errors.JSONMarshalError.Wrap(err)
}

// UnmarshalJSON unmarshals JSON into this
//
// implements json.Unmarshaler
func (event *OpenMessageTypingEvent) UnmarshalJSON(payload []byte) (err error) {
type surrogate OpenMessageTypingEvent
var inner struct {
surrogate
Type string `json:"eventType"`
Typing *struct {
Type string `json:"type"`
Duration int `json:"duration"`
} `json:"typing"`
}
if err = json.Unmarshal(payload, &inner); errors.Is(err, errors.JSONUnmarshalError) {
return err
} else if err != nil {
return errors.JSONUnmarshalError.Wrap(err)
}
*event = OpenMessageTypingEvent(inner.surrogate)

if inner.Typing != nil {
event.IsTyping = inner.Typing.Type == "On"
event.Duration = time.Duration(inner.Typing.Duration) * time.Millisecond
} else {
event.IsTyping = true
}
return nil
}
81 changes: 81 additions & 0 deletions openmessaging_message_events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package gcloudcx

import (
"encoding/json"

"github.com/gildas/go-errors"
)

// OpenMessageText is a text message sent or received by the Open Messaging API
//
// See https://developer.genesys.cloud/commdigital/digital/openmessaging/inboundEventMessages
type OpenMessageEvents struct {
ID string `json:"id,omitempty"` // Can be anything
Channel *OpenMessageChannel `json:"channel"`
Direction string `json:"direction,omitempty"` // Can be "Inbound" or "Outbound"
Events []OpenMessageEvent `json:"events"`
Metadata map[string]string `json:"metadata,omitempty"`
}

// init initializes this type
func init() {
openMessageRegistry.Add(OpenMessageEvents{})
}

// GetType returns the type of this event
//
// implements core.TypeCarrier
func (message OpenMessageEvents) GetType() string {
return "Event"
}

// GetID gets the identifier of this
//
// implements OpenMessage
func (message OpenMessageEvents) GetID() string {
return message.ID
}

// MarshalJSON marshals this into JSON
//
// implements json.Marshaler
func (message OpenMessageEvents) MarshalJSON() ([]byte, error) {
type surrogate OpenMessageEvents

data, err := json.Marshal(struct {
surrogate
Type string `json:"type"`
}{
surrogate: surrogate(message),
Type: message.GetType(),
})
return data, errors.JSONMarshalError.Wrap(err)
}

// UnmarshalJSON unmarshals JSON into this
//
// implements json.Unmarshaler
func (message *OpenMessageEvents) UnmarshalJSON(payload []byte) (err error) {
type surrogate OpenMessageEvents
var inner struct {
surrogate
Type string `json:"type"`
Events []json.RawMessage `json:"events"`
}
if err = json.Unmarshal(payload, &inner); errors.Is(err, errors.JSONUnmarshalError) {
return err
} else if err != nil {
return errors.JSONUnmarshalError.Wrap(err)
}
*message = OpenMessageEvents(inner.surrogate)

message.Events = make([]OpenMessageEvent, 0, len(inner.Events))
for _, raw := range inner.Events {
event, err := UnmarshalOpenMessageEvent(raw)
if err != nil {
return err
}
message.Events = append(message.Events, event)
}
return
}
45 changes: 45 additions & 0 deletions openmessaging_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -412,3 +412,48 @@ func (suite *OpenMessagingSuite) TestCanStringifyIntegration() {
integration.Name = ""
suite.Assert().Equal(id.String(), integration.String())
}

func (suite *OpenMessagingSuite) TestCanMarshalTypingEvent() {
channel := gcloudcx.NewOpenMessageChannel(
"",
nil,
&gcloudcx.OpenMessageFrom{
ID: "abcdef12345",
Type: "Email",
Firstname: "Bob",
Lastname: "Minion",
Nickname: "Bobby",
},
)
channel.Time = time.Date(2021, 4, 9, 4, 43, 33, 0, time.UTC)
event := gcloudcx.OpenMessageEvents{
Channel: channel,
Events: []gcloudcx.OpenMessageEvent{
gcloudcx.OpenMessageTypingEvent{IsTyping: true},
},
}
payload, err := json.Marshal(event)
suite.Require().NoErrorf(err, "Failed to marshal OpenMessageEvents. %s", err)
expected := suite.LoadTestData("openmessaging-event-typing.json")
suite.Require().JSONEq(string(expected), string(payload))
}

func (suite *OpenMessagingSuite) TestCanUnmarshalTypingEvent() {
payload := suite.LoadTestData("inbound-openmessaging-event-typing.json")
message, err := gcloudcx.UnmarshalOpenMessage(payload)
suite.Require().NoError(err, "Failed to unmarshal OpenMessage")
suite.Require().NotNil(message, "Unmarshaled message should not be nil")

actual, ok := message.(*gcloudcx.OpenMessageEvents)
suite.Require().True(ok, "Unmarshaled message should be of type OpenMessageEvents, but was %T", message)
suite.Require().NotNil(actual, "Unmarshaled message should not be nil")
suite.Assert().Equal("6ffd815bca1570e46251fcc71c103837", actual.ID)
suite.Assert().Equal(uuid.MustParse("1af69355-f1b0-477e-8ed9-66baff370209"), actual.Channel.ID)
suite.Assert().Equal("Outbound", actual.Direction)
suite.Require().Len(actual.Events, 1, "Unmarshaled message should have 1 event")

messageEvent, ok := actual.Events[0].(*gcloudcx.OpenMessageTypingEvent)
suite.Require().True(ok, "Unmarshaled message event should be of type *OpenMessageTypingEvent, but was %T", actual.Events[0])
suite.Assert().True(messageEvent.IsTyping)
suite.Assert().Equal(5*time.Second, messageEvent.Duration)
}
29 changes: 29 additions & 0 deletions testdata/inbound-openmessaging-event-typing.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"id": "6ffd815bca1570e46251fcc71c103837",
"channel": {
"id": "1af69355-f1b0-477e-8ed9-66baff370209",
"platform": "Open",
"type": "Private",
"to": {
"id": "abcdef12345"
},
"from": {
"nickname": "TEST-GO-PURECLOUD",
"id": "1af69355-f1b0-477e-8ed9-66baff370209",
"idType": "Opaque"
},
"time": "2023-09-19T08:25:16.925Z",
"messageId": "6ffd815bca1570e46251fcc71c103837"
},
"type": "Event",
"events": [
{
"eventType": "Typing",
"typing": {
"type": "On",
"duration": 5000
}
}
],
"direction": "Outbound"
}
18 changes: 18 additions & 0 deletions testdata/openmessaging-event-typing.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"channel": {
"platform": "Open",
"type": "Private",
"from": {
"id": "abcdef12345",
"idType": "Email",
"firstName": "Bob",
"lastName": "Minion",
"nickname": "Bobby"
},
"time": "2021-04-09T04:43:33Z"
},
"type": "Event",
"events": [
{ "eventType": "Typing" }
]
}
2 changes: 1 addition & 1 deletion version.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package gcloudcx
var commit string

// VERSION is the version of this application
var VERSION = "0.8.7" + commit
var VERSION = "0.8.8" + commit

// APP is the name of the application
const APP string = "GCloudCX Client"

0 comments on commit 572f13a

Please sign in to comment.