-
Notifications
You must be signed in to change notification settings - Fork 20
/
msg.go
146 lines (123 loc) · 3.95 KB
/
msg.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package inputs
import (
"encoding/json"
"strings"
"time"
"github.com/nyaruka/gocommon/jsonx"
"github.com/nyaruka/gocommon/urns"
"github.com/nyaruka/goflow/assets"
"github.com/nyaruka/goflow/envs"
"github.com/nyaruka/goflow/excellent/types"
"github.com/nyaruka/goflow/flows"
"github.com/nyaruka/goflow/utils"
)
func init() {
registerType(TypeMsg, readMsgInput)
}
// TypeMsg is a constant for incoming messages
const TypeMsg string = "msg"
// MsgInput is a message which can be used as input
type MsgInput struct {
baseInput
urn *flows.ContactURN
text string
attachments []utils.Attachment
externalID string
}
// NewMsg creates a new user input based on a message
func NewMsg(assets flows.SessionAssets, msg *flows.MsgIn, createdOn time.Time) *MsgInput {
// load the channel
var channel *flows.Channel
if msg.Channel() != nil {
channel = assets.Channels().Get(msg.Channel().UUID)
}
return &MsgInput{
baseInput: newBaseInput(TypeMsg, flows.InputUUID(msg.UUID()), channel, createdOn),
urn: flows.NewContactURN(msg.URN(), nil),
text: msg.Text(),
attachments: msg.Attachments(),
externalID: msg.ExternalID(),
}
}
// Context returns the properties available in expressions
//
// __default__:text -> the text and attachments
// uuid:text -> the UUID of the input
// created_on:datetime -> the creation date of the input
// channel:channel -> the channel that the input was received on
// urn:text -> the contact URN that the input was received on
// text:text -> the text part of the input
// attachments:[]text -> any attachments on the input
// external_id:text -> the external ID of the input
//
// @context input
func (i *MsgInput) Context(env envs.Environment) map[string]types.XValue {
attachments := make([]types.XValue, len(i.attachments))
for i, attachment := range i.attachments {
attachments[i] = types.NewXText(string(attachment))
}
var urn types.XValue
if i.urn != nil {
urn = i.urn.ToXValue(env)
}
return map[string]types.XValue{
"__default__": types.NewXText(i.format()),
"type": types.NewXText(i.type_),
"uuid": types.NewXText(string(i.uuid)),
"created_on": types.NewXDateTime(i.createdOn),
"channel": flows.Context(env, i.channel),
"urn": urn,
"text": types.NewXText(i.text),
"attachments": types.NewXArray(attachments...),
"external_id": types.NewXText(i.externalID),
}
}
func (i *MsgInput) format() string {
var parts []string
if i.text != "" {
parts = append(parts, i.text)
}
for _, attachment := range i.attachments {
parts = append(parts, attachment.URL())
}
return strings.Join(parts, "\n")
}
var _ flows.Input = (*MsgInput)(nil)
//------------------------------------------------------------------------------------------
// JSON Encoding / Decoding
//------------------------------------------------------------------------------------------
type msgInputEnvelope struct {
baseInputEnvelope
URN urns.URN `json:"urn" validate:"omitempty,urn"`
Text string `json:"text"`
Attachments []utils.Attachment `json:"attachments,omitempty"`
ExternalID string `json:"external_id,omitempty"`
}
func readMsgInput(sessionAssets flows.SessionAssets, data json.RawMessage, missing assets.MissingCallback) (flows.Input, error) {
e := &msgInputEnvelope{}
err := utils.UnmarshalAndValidate(data, e)
if err != nil {
return nil, err
}
i := &MsgInput{
urn: flows.NewContactURN(e.URN, nil),
text: e.Text,
attachments: e.Attachments,
externalID: e.ExternalID,
}
if err := i.unmarshal(sessionAssets, &e.baseInputEnvelope, missing); err != nil {
return nil, err
}
return i, nil
}
// MarshalJSON marshals this msg input into JSON
func (i *MsgInput) MarshalJSON() ([]byte, error) {
e := &msgInputEnvelope{
URN: i.urn.URN(),
Text: i.text,
Attachments: i.attachments,
ExternalID: i.externalID,
}
i.marshal(&e.baseInputEnvelope)
return jsonx.Marshal(e)
}