Skip to content

Commit

Permalink
Add URN field to trigger_session action instead of urn_match inside t…
Browse files Browse the repository at this point in the history
…he contact reference
  • Loading branch information
rowanseymour committed Oct 1, 2024
1 parent 6b43aa0 commit da76c4e
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 30 deletions.
23 changes: 22 additions & 1 deletion flows/actions/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,6 @@ func TestConstructors(t *testing.T) {
actions.NewStartSession(
actionUUID,
assets.NewFlowReference(assets.FlowUUID("fece6eac-9127-4343-9269-56e88f391562"), "Parent"),

[]*assets.GroupReference{
assets.NewGroupReference(assets.GroupUUID("b7cf0d83-f1c9-411c-96fd-c511a4cfa86d"), "Testers"),
},
Expand Down Expand Up @@ -734,6 +733,28 @@ func TestConstructors(t *testing.T) {
"create_contact": true
}`,
},
{
actions.NewTriggerSession(
actionUUID,
assets.NewFlowReference(assets.FlowUUID("fece6eac-9127-4343-9269-56e88f391562"), "Parent"),
flows.NewContactReference(flows.ContactUUID("cbe87f5c-cda2-4f90-b5dd-0ac93a884950"), "Bob Smith"),
"",
true,
),
`{
"type": "trigger_session",
"uuid": "ad154980-7bf7-4ab8-8728-545fd6378912",
"flow": {
"uuid": "fece6eac-9127-4343-9269-56e88f391562",
"name": "Parent"
},
"contact": {
"uuid": "cbe87f5c-cda2-4f90-b5dd-0ac93a884950",
"name": "Bob Smith"
},
"interrupt": true
}`,
},
}

for _, tc := range tests {
Expand Down
3 changes: 2 additions & 1 deletion flows/actions/testdata/send_broadcast.json
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@
"name": "Stavros"
},
{
"uuid": "11708c34-d4ab-4b04-b82a-2578f6e0013c"
"uuid": "11708c34-d4ab-4b04-b82a-2578f6e0013c",
"name": ""
}
],
"contact_query": "name = \"Bob\"",
Expand Down
70 changes: 70 additions & 0 deletions flows/actions/testdata/trigger_session.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,5 +129,75 @@
}
}
]
},
{
"description": "Session triggered event with URN",
"action": {
"type": "trigger_session",
"uuid": "ad154980-7bf7-4ab8-8728-545fd6378912",
"flow": {
"uuid": "b7cf0d83-f1c9-411c-96fd-c511a4cfa86d",
"name": "Collect Age"
},
"urn": "@(\"tel:+593979123456\")",
"interrupt": true
},
"events": [
{
"type": "session_triggered",
"created_on": "2018-10-18T14:20:30.000123456Z",
"step_uuid": "59d74b86-3e2f-4a93-aece-b05d2fdcde0c",
"flow": {
"uuid": "b7cf0d83-f1c9-411c-96fd-c511a4cfa86d",
"name": "Collect Age"
},
"urn": "tel:+593979123456",
"interrupt": true,
"exclusions": {},
"run_summary": {
"uuid": "e7187099-7d38-4f60-955c-325957214c42",
"flow": {
"uuid": "bead76f5-dac4-4c9d-996c-c62b326e8c0a",
"name": "Action Tester",
"revision": 123
},
"contact": {
"uuid": "5d76d86b-3bb9-4d5a-b822-c9d86f5d8e4f",
"name": "Ryan Lewis",
"language": "eng",
"last_seen_on": "2018-10-18T14:20:30.000123456Z",
"status": "active",
"timezone": "America/Guayaquil",
"created_on": "2018-06-20T11:40:30.123456789Z",
"urns": [
"tel:+12065551212?channel=57f1078f-88aa-46f4-a59a-948a5739c03d&id=123",
"twitterid:54784326227#nyaruka"
],
"groups": [
{
"uuid": "b7cf0d83-f1c9-411c-96fd-c511a4cfa86d",
"name": "Testers"
},
{
"uuid": "0ec97956-c451-48a0-a180-1ce766623e31",
"name": "Males"
}
],
"fields": {
"gender": {
"text": "Male"
}
}
},
"status": "active",
"results": {}
},
"history": {
"parent_uuid": "1ae96956-4b34-433e-8d1a-f05fe6923d6d",
"ancestors": 1,
"ancestors_since_input": 0
}
}
]
}
]
47 changes: 29 additions & 18 deletions flows/actions/trigger_session.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package actions

import (
"fmt"

"github.com/nyaruka/gocommon/jsonx"
"github.com/nyaruka/gocommon/urns"
"github.com/nyaruka/goflow/assets"
Expand All @@ -21,8 +23,8 @@ const TypeTriggerSession string = "trigger_session"

// TriggerSessionAction can be used to trigger sessions for another contact. A [event:session_triggered] event will be
// created and it's the responsibility of the caller to act on that by initiating a new session with the flow engine.
// The contact can be specified via a concrete reference or as a URN via the scheme and path fields. In the latter case
// the contact will be created if they don't exist.
// The contact can be specified via a reference or as a URN. In the latter case the contact will be created if they
// don't exist.
//
// {
// "uuid": "8eebd020-1af5-431c-b943-aa670fc74da9",
Expand All @@ -37,26 +39,36 @@ type TriggerSessionAction struct {
baseAction
onlineAction

Flow *assets.FlowReference `json:"flow" validate:"required"`
Contact *flows.ContactReference `json:"contact" validate:"required"`
Flow *assets.FlowReference `json:"flow" validate:"required"`
Contact *flows.ContactReference `json:"contact,omitempty"`
URN string `json:"urn,omitempty" engine:"evaluated"`
Interrupt bool `json:"interrupt"`
}

// NewTriggerSession creates a new trigger session action
func NewTriggerSession(uuid flows.ActionUUID, flow *assets.FlowReference, contact *flows.ContactReference, interrupt bool) *TriggerSessionAction {
func NewTriggerSession(uuid flows.ActionUUID, flow *assets.FlowReference, contact *flows.ContactReference, urn string, interrupt bool) *TriggerSessionAction {
return &TriggerSessionAction{
baseAction: newBaseAction(TypeTriggerSession, uuid),
Flow: flow,
Contact: contact,
URN: urn,
Interrupt: interrupt,
}
}

// Validate validates our action is valid
func (a *TriggerSessionAction) Validate() error {
if (a.Contact != nil && a.URN != "") || (a.Contact == nil && a.URN == "") {
return fmt.Errorf("must specify either contact or urn")

Check warning on line 62 in flows/actions/trigger_session.go

View check run for this annotation

Codecov / codecov/patch

flows/actions/trigger_session.go#L62

Added line #L62 was not covered by tests
}
return nil
}

// Execute runs our action
func (a *TriggerSessionAction) Execute(run flows.Run, step flows.Step, logModifier flows.ModifierCallback, logEvent flows.EventCallback) error {
contact := a.resolveContact(run, logEvent)
if contact == nil {
logEvent(events.NewDependencyError(a.Contact))
urn := a.resolveURN(run, logEvent)

if urn == urns.NilURN && a.Contact == nil {
return nil

Check warning on line 72 in flows/actions/trigger_session.go

View check run for this annotation

Codecov / codecov/patch

flows/actions/trigger_session.go#L72

Added line #L72 was not covered by tests
}

Expand All @@ -81,34 +93,33 @@ func (a *TriggerSessionAction) Execute(run flows.Run, step flows.Step, logModifi

history := flows.NewChildHistory(run.Session())

logEvent(events.NewSessionTriggered(flow.Reference(false), contact, a.Interrupt, runSnapshot, history))
logEvent(events.NewSessionTriggered(flow.Reference(false), a.Contact, urn, a.Interrupt, runSnapshot, history))
return nil
}

func (a *TriggerSessionAction) resolveContact(run flows.Run, logEvent flows.EventCallback) *flows.ContactReference {
// if this is a concrete reference, return as is
if !a.Contact.Variable() {
return a.Contact
func (a *TriggerSessionAction) resolveURN(run flows.Run, logEvent flows.EventCallback) urns.URN {
if a.URN == "" {
return urns.NilURN
}

// otherwise this is a variable reference so evaluate it
evaluatedURN, ok := run.EvaluateTemplate(a.Contact.URNMatch, logEvent)
evaluatedURN, ok := run.EvaluateTemplate(a.URN, logEvent)
if !ok {
return nil
return urns.NilURN

Check warning on line 108 in flows/actions/trigger_session.go

View check run for this annotation

Codecov / codecov/patch

flows/actions/trigger_session.go#L108

Added line #L108 was not covered by tests
}

// if we have a valid URN now, return it
urn := urns.URN(evaluatedURN)
if urn.Validate() == nil {
return &flows.ContactReference{URNMatch: string(urn.Normalize())}
return urn.Normalize()
}

// otherwise try to parse as phone number
parsedTel := utils.ParsePhoneNumber(evaluatedURN, run.Session().MergedEnvironment().DefaultCountry())
if parsedTel != "" {
urn, _ := urns.New(urns.Phone, parsedTel)
return &flows.ContactReference{URNMatch: string(urn.Normalize())}
return urn.Normalize()

Check warning on line 121 in flows/actions/trigger_session.go

View check run for this annotation

Codecov / codecov/patch

flows/actions/trigger_session.go#L118-L121

Added lines #L118 - L121 were not covered by tests
}

return nil
return urns.NilURN

Check warning on line 124 in flows/actions/trigger_session.go

View check run for this annotation

Codecov / codecov/patch

flows/actions/trigger_session.go#L124

Added line #L124 was not covered by tests
}
5 changes: 2 additions & 3 deletions flows/contact.go
Original file line number Diff line number Diff line change
Expand Up @@ -544,9 +544,8 @@ var _ contactql.Queryable = (*Contact)(nil)

// ContactReference is used to reference a contact
type ContactReference struct {
UUID ContactUUID `json:"uuid,omitempty" validate:"omitempty,uuid4"`
Name string `json:"name,omitempty"`
URNMatch string `json:"urn_match,omitempty" engine:"evaluated"`
UUID ContactUUID `json:"uuid" validate:"required,uuid4"`
Name string `json:"name"`
}

// NewContactReference creates a new contact reference with the given UUID and name
Expand Down
9 changes: 6 additions & 3 deletions flows/definition/legacy/testdata/actions.json
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,8 @@
"name": "Horatio"
},
{
"uuid": "cd0d8605-5abc-428c-b34b-c6f6e7a3ef42"
"uuid": "cd0d8605-5abc-428c-b34b-c6f6e7a3ef42",
"name": ""
}
],
"groups": [
Expand Down Expand Up @@ -595,10 +596,12 @@
"uuid": "5a4d00aa-807e-44af-9693-64b9fdedd352",
"contacts": [
{
"uuid": "879ace1b-740b-45f1-9198-c2f2f08a825f"
"uuid": "879ace1b-740b-45f1-9198-c2f2f08a825f",
"name": ""
},
{
"uuid": "cd0d8605-5abc-428c-b34b-c6f6e7a3ef42"
"uuid": "cd0d8605-5abc-428c-b34b-c6f6e7a3ef42",
"name": ""
}
],
"groups": [
Expand Down
4 changes: 1 addition & 3 deletions flows/definition/migrations/specdata/templates.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
"send_broadcast": [
".attachments[*]",
".contact_query",
".contacts[*].urn_match",
".groups[*].name_match",
".legacy_vars[*]",
".quick_replies[*]",
Expand Down Expand Up @@ -73,13 +72,12 @@
],
"start_session": [
".contact_query",
".contacts[*].urn_match",
".groups[*].name_match",
".legacy_vars[*]"
],
"transfer_airtime": [],
"trigger_session": [
".contact.urn_match"
".urn"
]
},
"routers": {
Expand Down
4 changes: 3 additions & 1 deletion flows/events/session_triggered.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type SessionTriggeredEvent struct {

Flow *assets.FlowReference `json:"flow" validate:"required"`
Contact *flows.ContactReference `json:"contact,omitempty"`
URN urns.URN `json:"urn,omitempty" validate:"omitempty,urn"`
Interrupt bool `json:"interrupt,omitempty"`
RunSummary json.RawMessage `json:"run_summary"`
History *flows.SessionHistory `json:"history"`
Expand All @@ -72,11 +73,12 @@ type SessionTriggeredEvent struct {
}

// NewSessionTriggered returns a new session triggered event
func NewSessionTriggered(flow *assets.FlowReference, contact *flows.ContactReference, interrupt bool, runSummary json.RawMessage, history *flows.SessionHistory) *SessionTriggeredEvent {
func NewSessionTriggered(flow *assets.FlowReference, contact *flows.ContactReference, urn urns.URN, interrupt bool, runSummary json.RawMessage, history *flows.SessionHistory) *SessionTriggeredEvent {
return &SessionTriggeredEvent{
BaseEvent: NewBaseEvent(TypeSessionTriggered),
Flow: flow,
Contact: contact,
URN: urn,
Interrupt: interrupt,
RunSummary: runSummary,
History: history,

Check warning on line 84 in flows/events/session_triggered.go

View check run for this annotation

Codecov / codecov/patch

flows/events/session_triggered.go#L76-L84

Added lines #L76 - L84 were not covered by tests
Expand Down

0 comments on commit da76c4e

Please sign in to comment.