I'm still in my trial phase with Twilio and working on putting together a "flow" in Studio to handle my use-case properly. So far, all of the basic, plain-text steps in my flow seem to be working exactly as expected, but I'm having problems figuring out how to handle incoming media/attachments the way I want. I readily admit and acknowledge that what I've put together may not be the most effective solution, but it's what I've come up with based on the research I've done so far.
First, here is the basic breakdown of the desired steps in my flow:
- I have a separate application that connects to the Twilio REST API to initiate the flow's execution. It passes a couple of parameters into the flow's
flow.data
namespace for inclusion in various messages sent to the end-user as a part of the flow.Private Async Sub StartFlow(ByVal Recipient As String) Try Dim RefNum As String = GenerateReferenceNumber(8) Dim NoticeParameters As New Dictionary(Of String, Object) From { {"ref_num", RefNum}, {"contact_num", "(800) 555-1234"}, {"client_name", "Caliente Client"} } TwilioClient.Init(SID, Token) Dim FlowExecution = Await ExecutionResource.CreateAsync(parameters:=NoticeParameters, [to]:=New PhoneNumber(Recipient), from:=MyTwilioNumber, pathFlowSid:=NoticeFlowSID) Catch ex As Exception End Try End Sub
- The first step in the flow's execution is to initialize a variable in the
flow.variables
namespace namedcurrent_response
with a value ofEMPTY
. - The flow's next step is to send our initial SMS contact to the end-user via a Send & Wait For Reply widget called "
Notice
". - When a reply is received from the user, the
flow.variables.current_response
value is updated by a Set Variables widget:- If the value of
widgets.Notice.inbound.MediaUrl0
is notNULL
, theflow.variables.current_response
value is set to the URL value from that property. - If the value of
widgets.Notice.inbound.MediaUrl0
isNULL
, theflow.variables.current_response
value is set to the value of thewidgets.Notice.inbound.Body
property instead.
- If the value of
- After setting the
current_response
variable's value, that variable is passed on to a Split Based On... widget (named "Response_Received
") that tests theflow.variables.current_response
with the following Regular Expression to determine whether or not the value is a URL:[(http(s)?):\/\/(www\.)?a-zA-Z0-9@:%._\ ~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\ .~#?&//=]*)
- If the value is not a URL, the flow should pass execution on to the next Split Based On... widget (named "
Other_Response
") to handle certain plain-text replies with a pre-defined set of responses. - If the value is a URL, it should pass execution to a Make HTTP Request widget that will POST to my MVC controller to log the incoming file.
- If the value is not a URL, the flow should pass execution on to the next Split Based On... widget (named "
- Depending on the end-user's reply, the
Other_Response
widget will then pass execution on to another Send & Wait For Reply widget that can update theflow.variables.current_response
property with that widget'sinbound.MediaUrl0
orinbound.Body
via another Set Variables widget if they continue the conversation. - After updating the
current_response
variable, flow execution returns to the "Response_Received
" widget with the new value (see #5).
The idea is that, if the user initially responds with something like HELP
, I want to be able to send them a message with additional details about the reason we reached out to them in the first place, then allow them to send us the specific information (file) we're requesting while still retaining the values I populated into the flow from my in-house application - most specifically, a unique reference number I've generated for the contact. Even if it takes them a couple of tries, as long as the execution is valid, I want any reply within that execution to have the capability of processing an incoming file based on those same values.
In my tests, I've been able to get all of the simple, plain-text responses to work as I've designed:
- I reply to the flow's initial message with one of the pre-defined messages and the flow returns the correct response and waits.
- I reply to that message with another of the pre-defined messages and the flow again returns the appropriate response and waits.
- I reply to that message with a plain-text message that isn't defined as a valid response and the flow correctly returns a message stating, "I'm sorry. I didn't recognize your response. Please try again."
However, if I reply to the flow's initial message with a file as I expect to have our end-users doing (I've used PDF and PNG files in my testing so far), I still get the message stating, "I'm sorry. I didn't recognize your response. Please try again." This message is not defined in the path from the split designated for replies with a URL.
Based on the results, I can only assume that there's something "wrong" with the RegEx logic that's not actually matching the URL as it should. I've
I am continuing to work with the Twilio Support team as well to determine if there's an actual "problem" here, or if I'm simply doing it wrong (a distinct possibility). There very well may be more effective/efficient ways to achieve my goals but, in the absence of a "generic" option to validate any incoming widget (e.g., widgets.previous_widget.inbound.MediaUrl0
), this is the best solution I've been able to find so far.
The main reason I'm posting my question here is not only to try and find a solution that fits my specific needs, but also to document the troubleshooting process and hopefully help anyone else who's just beginning to work with Studio and needs to implement some "complex" business rules.
UPDATE - Alternative Solution Found
So, after talking it through with Twilio Support, we still weren't able to figure out why the above method doesn't work, but we were able to determine that the current best course of action is to add a series of Split Based On... widgets into the flow at each point where I currently just have the Set Variables widgets. While it significantly increases the overall complexity of the flow itself, this method eliminates the need to use the RegEx matching I had to identify incoming URLs.
Even so, once I was finally able to properly articulate why I was trying to make this work, the representative with whom I spoke agreed that it should work and is going to continue testing and investigating the issue. In the meantime, I'm going to update my flow to add all of the extra widgets I need for my logic, but I'd still like to find out if there's some reason I'm overlooking why this is failing.
CodePudding user response:
Based on my conversations with the Twilio Support team, it seems that, for whatever reason, the RegEx method I had implemented will not work. I wasn't able to get a specific reason why it fails, but it appears to be a technical limitation somewhere within Studio. In this case, to achieve my specific goals, there are basically two alternatives:
- As I described in the UPDATE in the OP, I can use Split Based On... widgets at each Send & Wait For Reply point that test whether the
MediaUrl0
value is empty, then use a pair of Set Variables widgets - one for text-only replies and one for replies with attachments - to pass the value(s) on to the appropriate next step in the flow. - Instead of using a
RegEx
match to test the value of mycurrent_response
variable, I can use theStarts With
test to see if thecurrent_response
begins with "my" Twilio API URL (https://api.twilio.com/2010-04-01/Accounts/[ACCOUNT SID]/Messages
).
Obviously, the former method requires a bit more complexity - several additional widgets to direct the flow to the appropriate next widget - but is less dependent on the actual value of the Twilio API URL. The only "problem" with the latter method would be that if the API version (2010-04-01
) changes, I would need to update each point in my flow where it's used to reference the new version.
At this time, I've opted for the former solution and have tested the flow several times to ensure that it all seems to be working correctly. After a few "false starts", I've been able to get through the entire process with all of the correct responses and operations. Simple text replies send back the appropriate response while sending a file pushes the information over to my MVC controller for further processing.
One totally tangential side note: Because the MediaUrl0
value "masks" the original file name and strips the file extension, I needed a way to determine what kind of file was being sent. In a "regular" SMS interaction using Twilio's Programmable Messaging tools, there's a MediaContentType0
property. This value is not a selectable option in the Studio flow editor. I was able to retrieve the value of this property by manually typing it into the appropriate fields (widgets.[WIDGET_NAME].inbound.MediaContentType0
), so it seems that any value that is available in the current JSON should be accessible through Studio. You just have to know what you're looking for because it isn't "documented". I hope this all helps someone else looking to implement their own Studio flow.