Skip to content

Commit

Permalink
Merge branch 'release/0.7.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
gildas committed Nov 24, 2021
2 parents cf52dc0 + 007b467 commit f153d10
Show file tree
Hide file tree
Showing 55 changed files with 1,636 additions and 729 deletions.
70 changes: 67 additions & 3 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,73 @@ func (client *Client) IsAuthorized() bool {
return client.Grant.AccessToken().IsValid()
}

// Fetch fetches an initializable object
func (client *Client) Fetch(context context.Context, object Initializable) error {
return object.Initialize(context, client)
// Fetch fetches an object from the Genesys Cloud API
//
// The object must implement the Fetchable interface
//
// Objects can be fetched by their ID:
//
// client.Fetch(context, &User{ID: uuid.UUID})
//
// client.Fetch(context, &User{}, uuid.UUID)
//
// or by their name:
//
// client.Fetch(context, &User{}, "user-name")
//
// or by their URI:
//
// client.Fetch(context, &User{}, URI("/api/v2/users/user-id"))
//
// client.Fetch(context, &User{URI: "/api/v2/users/user-id"})
func (client *Client) Fetch(ctx context.Context, object Fetchable, parameters ...interface{}) error {
if _, err := logger.FromContext(ctx); err != nil {
ctx = client.Logger.ToContext(ctx)
}
return object.Fetch(ctx, client, parameters...)
}

// ParseParameters parses the parameters to get an id, name or URI
//
// the id can be a string or a uuid.UUID, or coming from the object
//
// the uri can be a URI, or coming from the object
//
// a logger.Logger is also returned, either from the context or the client
func (client *Client) ParseParameters(ctx context.Context, object interface{}, parameters ...interface{}) (uuid.UUID, string, URI, *logger.Logger) {
var (
id uuid.UUID = uuid.Nil
name string
uri URI
)

for _, parameter := range parameters {
switch parameter := parameter.(type) {
case uuid.UUID:
id = parameter
case string:
name = parameter
case URI:
uri = parameter
}
}
if identifiable, ok := object.(Identifiable); id == uuid.Nil && ok {
id = identifiable.GetID()
}
if addressable, ok := object.(Addressable); len(uri) == 0 && ok {
uri = addressable.GetURI()
}
log, err := logger.FromContext(ctx)
if err != nil {
log = client.Logger
}
if typed, ok := object.(core.TypeCarrier); ok {
log = log.Child(typed.GetType(), typed.GetType())
}
if id != uuid.Nil {
log = log.Record("id", id.String())
}
return id, name, uri, log
}

// CheckPermissions checks if the current client has the given permissions
Expand Down
38 changes: 24 additions & 14 deletions conversation.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gcloudcx

import (
"context"
"time"

"github.com/gildas/go-logger"
Expand All @@ -11,7 +12,7 @@ import (
// See: https://developer.mypurecloud.com/api/rest/v2/conversations
type Conversation struct {
ID uuid.UUID `json:"id"`
SelfURI string `json:"selfUri,omitempty"`
SelfURI URI `json:"selfUri,omitempty"`
Name string `json:"name"`
StartTime time.Time `json:"startTime"`
EndTime time.Time `json:"endTime"`
Expand All @@ -25,9 +26,8 @@ type Conversation struct {
Division DomainEntityRef `json:"division"`
Entities []DomainEntityRef `json:"entities"`
} `json:"divisions"`

Client *Client `json:"-"`
Logger *logger.Logger `json:"-"`
client *Client `json:"-"`
logger *logger.Logger `json:"-"`
}

// ConversationRoutingData defines routing details of a Conversation
Expand Down Expand Up @@ -76,20 +76,24 @@ type Voicemail struct {
UploadStatus string `json:"uploadStatus"`
}

// Initialize initializes this from the given Client
// implements Initializable
func (conversation *Conversation) Initialize(parameters ...interface{}) error {
context, client, logger, id, err := parseParameters(conversation, parameters...)
if err != nil {
return err
}
// Fetch fetches the conversation
//
// implements Fetchable
func (conversation *Conversation) Fetch(ctx context.Context, client *Client, parameters ...interface{}) error {
id, _, selfURI, log := client.ParseParameters(ctx, conversation, parameters...)

if id != uuid.Nil {
if err := conversation.Client.Get(context, NewURI("/conversations/%s", id), &conversation); err != nil {
if err := client.Get(ctx, NewURI("/conversations/%s", id), &conversation); err != nil {
return err
}
conversation.logger = log
} else if len(selfURI) > 0 {
if err := client.Get(ctx, selfURI, &conversation); err != nil {
return err
}
conversation.logger = log.Record("id", conversation.ID)
}
conversation.Client = client
conversation.Logger = logger.Topic("conversation").Scope("conversation").Record("media", "chat")
conversation.client = client
return nil
}

Expand All @@ -99,6 +103,12 @@ func (conversation Conversation) GetID() uuid.UUID {
return conversation.ID
}

// GetURI gets the URI of this
// implements Addressable
func (conversation Conversation) GetURI() URI {
return conversation.SelfURI
}

// String gets a string version
// implements the fmt.Stringer interface
func (conversation Conversation) String() string {
Expand Down
32 changes: 22 additions & 10 deletions conversation_agentless.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,26 @@ type TemplateParameter struct {

// AgentlessMessageResult describes the results of the send action on an AgentlessMessage
type AgentlessMessageResult struct {
ID string `json:"id"`
ConversationID uuid.UUID `json:"conversationId"`
From string `json:"fromAddress"`
To string `json:"toAddress"`
MessengerType string `json:"messengerType"`
Text string `json:"textBody"`
Template *MessagingTemplate `json:"messagingTemplate,omitempty"`
JobUser *AddressableEntityRef `json:"user,omitempty"`
Timestamp time.Time `json:"timestamp"`
SelfURI string `json:"selfUri"`
ID uuid.UUID `json:"id"`
ConversationID uuid.UUID `json:"conversationId"`
From string `json:"fromAddress"`
To string `json:"toAddress"`
MessengerType string `json:"messengerType"`
Text string `json:"textBody"`
Template *MessagingTemplate `json:"messagingTemplate,omitempty"`
JobUser *AddressableEntityRef `json:"user,omitempty"`
Timestamp time.Time `json:"timestamp"`
SelfURI URI `json:"selfUri"`
}

// GetID gets the identifier of this
// implements Identifiable
func (result AgentlessMessageResult) GetID() uuid.UUID {
return result.ID
}

// GetURI gets the URI of this
// implements Addressable
func (result AgentlessMessageResult) GetURI() URI {
return result.SelfURI
}
60 changes: 34 additions & 26 deletions conversation_chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
// ConversationChat describes a Agent-side Chat
type ConversationChat struct {
ID uuid.UUID `json:"id"`
SelfURI string `json:"selfUri,omitempty"`
SelfURI URI `json:"selfUri,omitempty"`
State string `json:"state"` // alerting,dialing,contacting,offering,connected,disconnected,terminated,converting,uploading,transmitting,scheduled,none
Direction string `json:"direction"` // inbound,outbound
DisconnectType string `json:"disconnectType"` // endpoint,client,system,transfer,timeout,transfer.conference,transfer.consult,transfer.forward,transfer.noanswer,transfer.notavailable,transport.failure,error,peer,other,spam,uncallable
Expand All @@ -33,8 +33,8 @@ type ConversationChat struct {
RecordingID string `json:"recordingId"`
AvatarImageURL *url.URL `json:"-"`
JourneyContext *JourneyContext `json:"journeyContext"`
Client *Client `json:"-"`
Logger *logger.Logger `json:"-"`
client *Client `json:"-"`
logger *logger.Logger `json:"-"`
}

// JourneyContext describes a Journey Context
Expand All @@ -56,22 +56,24 @@ type JourneyContext struct {
} `json:"triggeringAction"`
}

// Initialize initializes this from the given Client
// implements Initializable
func (conversation *ConversationChat) Initialize(parameters ...interface{}) error {
context, client, logger, id, err := parseParameters(conversation, parameters...)
if err != nil {
return err
}
// TODO: get /conversations/chats/$id when that REST call works better
// At the moment, chat participants do not have any chats even if they are connected. /conversations/$id looks fine
// Fetch fetches a Chat Conversation
//
// implements Fetchable
func (conversation *ConversationChat) Fetch(ctx context.Context, client *Client, parameters ...interface{}) error {
id, _, selfURI, log := client.ParseParameters(ctx, conversation, parameters...)

if id != uuid.Nil {
if err := conversation.Client.Get(context, NewURI("/conversations/%s", id), &conversation); err != nil {
if err := client.Get(ctx, NewURI("/conversations/%s", id), &conversation); err != nil {
return err
}
conversation.logger = log.Record("media", "chat")
} else if len(selfURI) > 0 {
if err := client.Get(ctx, selfURI, &conversation); err != nil {
return err
}
conversation.logger = log.Record("id", conversation.ID).Record("media", "chat")
}
conversation.Client = client
conversation.Logger = logger.Topic("conversation").Scope("conversation").Record("media", "chat")
conversation.client = client
return nil
}

Expand All @@ -81,6 +83,12 @@ func (conversation ConversationChat) GetID() uuid.UUID {
return conversation.ID
}

// GetURI gets the URI of this
// implements Addressable
func (conversation ConversationChat) GetURI() URI {
return conversation.SelfURI
}

// String gets a string version
// implements the fmt.Stringer interface
func (conversation ConversationChat) String() string {
Expand All @@ -90,8 +98,8 @@ func (conversation ConversationChat) String() string {
// Disconnect disconnect an Identifiable from this
// implements Disconnecter
func (conversation ConversationChat) Disconnect(context context.Context, identifiable Identifiable) error {
return conversation.Client.Patch(
context,
return conversation.client.Patch(
conversation.logger.ToContext(context),
NewURI("/conversations/chats/%s/participants/%s", conversation.ID, identifiable.GetID()),
MediaParticipantRequest{State: "disconnected"},
nil,
Expand All @@ -101,8 +109,8 @@ func (conversation ConversationChat) Disconnect(context context.Context, identif
// UpdateState update the state of an identifiable in this
// implements StateUpdater
func (conversation ConversationChat) UpdateState(context context.Context, identifiable Identifiable, state string) error {
return conversation.Client.Patch(
context,
return conversation.client.Patch(
conversation.logger.ToContext(context),
NewURI("/conversations/chats/%s/participants/%s", conversation.ID, identifiable.GetID()),
MediaParticipantRequest{State: state},
nil,
Expand All @@ -112,8 +120,8 @@ func (conversation ConversationChat) UpdateState(context context.Context, identi
// Transfer transfers a participant of this Conversation to the given Queue
// implement Transferrer
func (conversation ConversationChat) Transfer(context context.Context, identifiable Identifiable, queue Identifiable) error {
return conversation.Client.Post(
context,
return conversation.client.Post(
conversation.logger.ToContext(context),
NewURI("/conversations/chats/%s/participants/%s/replace", conversation.ID, identifiable.GetID()),
struct {
ID string `json:"queueId"`
Expand All @@ -124,8 +132,8 @@ func (conversation ConversationChat) Transfer(context context.Context, identifia

// Post sends a text message to a chat member
func (conversation ConversationChat) Post(context context.Context, member Identifiable, text string) error {
return conversation.Client.Post(
context,
return conversation.client.Post(
conversation.logger.ToContext(context),
NewURI("/conversations/chats/%s/communications/%s/messages", conversation.ID, member.GetID()),
struct {
BodyType string `json:"bodyType"`
Expand All @@ -140,8 +148,8 @@ func (conversation ConversationChat) Post(context context.Context, member Identi

// SetTyping send a typing indicator to the chat member
func (conversation ConversationChat) SetTyping(context context.Context, member Identifiable) error {
return conversation.Client.Post(
context,
return conversation.client.Post(
conversation.logger.ToContext(context),
NewURI("/conversations/chats/%s/communications/%s/typing", conversation.ID, member.GetID()),
nil,
nil,
Expand All @@ -150,7 +158,7 @@ func (conversation ConversationChat) SetTyping(context context.Context, member I

// Wrapup wraps up a Participant of this Conversation
func (conversation ConversationChat) Wrapup(context context.Context, identifiable Identifiable, wrapup *Wrapup) error {
return conversation.Client.Patch(
return conversation.client.Patch(
context,
NewURI("/conversations/chats/%s/participants/%s", conversation.ID, identifiable.GetID()),
MediaParticipantRequest{Wrapup: wrapup},
Expand Down
Loading

0 comments on commit f153d10

Please sign in to comment.