sending flow.variables to twilio function - twilio

In Twilio Studio I'm setting a number of variables. I then need to send them to a function. I'm using {{flow.variables}} as a parameter to the function. The result I'm getting in the function is
{
All_VARS: '{childcare=yes, camp=yes}'
}
Why is this formatted as a string with =? I would expect {childcare: 'yes', camp: 'yes'}
when I send each variable separately with {{flow.variables.<key>}}I get what I would expect
{
campVar: 'yes',
childcareVar: 'yes'
}
But I don't want to send all the flow set variables individually as parameters, it seems that I should be able simply use {{flow.variables}} but the return value is not usable. What am I missing?

Related

Use generic-webhook-trigger and pass JSON body as is instead of individual variables

I am using generic-webhook-trigger in Jenkins to trigger job when events happen in Github.
It seems I have to extract each variable I need from the big JSON request body to convert them to env-var.
Is it possible to pass the whole JSON body to the Jenkins job and have it parse it?
You can achieve what you want by assigning the entire body to a specific variable, then read it as Json in your code and parse it by yourself.
For example, if your payload (received post content) is:
{
"ref": "refs/heads/master",
"head_commit": {
"committer": {
"name": "ido",
"email": "ido#test.com"
}
}
}
You can define a single parameter in your generic webhook configuration called payload, set the expression for that parameter to $, set the expressionType JSONPath, and when the job is triggered that parameter will include the entire content of the received post content.
You can then parse it by yourself:
def payloadMap = readJSON text: payload
println "ref value is: ${payloadMap.ref}"
println "committer name is: ${payloadMap.head_commit.committer.name}"
You can see more advanced examples for using the generic-webhook-trigger configurations plugin Here, and especially This one which is more relevant for your requirements.

Include multiple incoming SMS messages/responses with Twilio functions

I'm working on a project now within Twilio, using Twilio Functions, where I'm trying to set up SMS messaging so that if we receive an incoming keyword, we respond with a specific message, including a URL. The plan is to have multiple incoming keywords, with different responses so if someone sends an SMS to one of our numbers, depending on that key word, we respond with a basic message and a URL. I'm trying to figure out the best way to handle this within Twilio Functions.
I have this working for a single incoming keyword/response, as seen below.
if (incomingMessage.includes('testpark')) {
twiml.message('StartMyParking:\n\nTo start your parking, please click this link: https://blahblah.com');
} else if (incomingMessage.includes('bye')) {
twiml.message('Goodbye!');
} else {
twiml.message('Please check your zone/code and try again.');
}
While that works, I want to add in more incoming words, along with responses, such as an incoming message of 'testpark2' and a response of 'StartMyParking:\n\nTo start your parking, please click this link: https://blahblah2.com'.
Then I would want to include another one with 'testpark3' and a response of 'StartMyParking:\n\nTo start your parking, please click this link: https://blahblah3.com' and so on, all within the same script.
Can someone help me understand how to achieve this?
There are a lot of ways to achieve your desired outcome, but here's the most straightforward to begin with.
Instead of creating an else if statement for every possible keyword, you could define the keyword/response pairs up front using a JavaScript Map.
The keys of the Map will be your keywords, the values of the Map will be your responses:
const keywordResponseMap = new Map([
['testpark2', 'StartMyParking:\n\nTo start your parking, please click this link: https://blahblah2.com'],
['testpark3', 'StartMyParking:\n\nTo start your parking, please click this link: https://blahblah3.com'],
['testpark', 'StartMyParking:\n\nTo start your parking, please click this link: https://blahblah.com'],
]);
const keywords = Array.from(keywordResponseMap.keys());
let keyword;
if (incomingMessage.includes('bye')) {
twiml.message('Goodbye!');
}
else if (keyword = keywords.find(k => incomingMessage.includes(k))) {
const response = keywordResponseMap.get(keyword);
twiml.message(response);
} else {
twiml.message('Please check your zone/code and try again.');
}
Also note that I'm putting the bye case up front because it is more performant than looking for the keywords in the incomingMessage, thus you avoid unnecessarily doing that processing when a user says bye.
You can use find to search for any keyword that is in the incomingMessage, then you can use the keyword that you found to retrieve the response from the map.
If your response will always be the same except for the URL, you could further optimize this by only storing the URL in the map and using string interpolation like this:
const keywordUrlMap = new Map([
['testpark2', 'https://blahblah2.com'],
['testpark3', 'https://blahblah3.com'],
['testpark', 'https://blahblah.com'],
]);
const keywords = Array.from(keywordUrlMap.keys());
let keyword;
if (incomingMessage.includes('bye')) {
twiml.message('Goodbye!');
}
else if (keyword = keywords.find(k => incomingMessage.includes(k))) {
const url = keywordUrlMap.get(keyword);
twiml.message(`StartMyParking:\n\nTo start your parking, please click this link: ${url}`);
} else {
twiml.message('Please check your zone/code and try again.');
}
It is also important to note that I'm putting testpark last in the map because testpark matches to testpark2 and testpark3. If you'd put it first, it would always resolve to testpark even with a user submits testpark2 or similar values.
Also, I'm using the Map type because it guarantees the order in which the keys are returned, which is again important for the previous point.
When you have a lot more keywords and responses, you may have to start looking at a solution to store them externally like a database, and query the database by keyword to resolve the response.
Good luck, we can't wait to see what you build!

Access session value in gatling checks

I use gatling to send data to an ActiveMQ. The payload is generated in a separate method. The response should also be validated. However, how can I access the session data within the checks
check(bodyString.is()) or simpleCheck(...)? I have also thought about storing the current payload in a separate global variable, but I don't know if this is the right approach. My code's setup looks like this at the moment:
val scn = scenario("Example ActiveMQ Scenario")
.exec(jms("Test").requestReply
.queue(...)
.textMessage{ session => val message = createPayload(); session.set("payload", payload); message}
.check(simpleCheck{message => customCheck(message, ?????? )})) //access stored payload value, alternative: check(bodystring.is(?????)
def customCheck(m: Message, string: String) = {
// check logic goes here
}
Disclaimer: providing example in Java as you don't seem to be a Scala developper, so Java would be a better fit for you (supported since Gatling 3.7).
The way you want to do things can't possibly work.
.textMessage(session -> {
String message = createPayload();
session.set("payload", payload);
return message;
}
)
As explained in the documentation, Session is immutable, so in a function that's supposed to return the payload, you can't also return a new Session.
What you would have to do it first store the payload in the session, then fetch it:
.exec(session -> session.set("payload", createPayload()))
...
.textMessage("#{payload}")
Regarding writing your check, simpleCheck doesn't have access to the Session. You have to use check(bodyString.is()) and pass a function to is, again as explained in the documentation.

setting 'replace_original' to false while responding to Slack message action request doesn't work

Background:
I am using the python slack API (slackclient) to build an iterative sequence of data-gathering actions in ephemeral messages.
The core of this works fine. After processing the incoming request that contains the user's interaction with a set of message buttons (or menus), I respond immediately with a JSON body, as described in the "Responding right away" section of the official slack docs.
The problem:
Every response replaces the preceding message+attachments. In many cases, this is what I want, but there are situations where I want to add a response rather than replace the previous message.
Per the slack docs,setting replace_original to false should do just that. But the following code, snipped from my handling of a simple button click (for example), replaces the original button (and the text message to which it was attached):
r = {
'response_type': 'ephemeral',
'text': 'foo',
'replace_original': 'false'
}
log.debug("Returning: {}".format(json.dumps(r)))
resp = Response(response=json.dumps(r),
mimetype="application/json",
status=200)
return resp
I have tried this with and without the delete_original and response_type fields, with no change.
In short, it appears that in this case the replace_original field isn't doing anything at all; behavior is always as if it were set to 'true'.
I feel like I must be missing something here - any help is greatly appreciated.
Simple solution here: the slack API is expecting a boolean, not a string. So 'replace_original': 'false' in the above snippet ends up as {"response_type": "ephemeral", "text": "foo", "replace_original": "false"} after the json.dumps() call, which is invalid.
Instead, setting 'replace_original': False becomes {"response_type": "ephemeral", "text": "foo", "replace_original": false}, which then has the expected behavior

How to use Twilio.Device to call a number

How to call to a phone number using Twilio.Device?
I am doing the click to call feature for my widget.
I am able to get the Capability token required in setting up the Twilio.Device. I am able also to connect the Twilio.Device to twilio by setup function provided in client javascript library.
What can I use to call a number using Twilio.Device?
Its been a while since I played with it, but looking back at the code then once you have the token and are connected to Twilio it's just a case of setting the number you want to call and then initiating the call. Something like this:
document.getElementById('button-call').onclick = function () {
// get the phone number to connect the call to
var params = {
Caller: document.getElementById('phone-number').value
};
console.log('Calling ' + params.Caller + '...');
Twilio.Device.connect(params);
};
You have to make sure your token allows outgoing calls. My token.php file contains the following:
$capability = new ClientToken($TWILIO_ACCOUNT_SID, $TWILIO_AUTH_TOKEN, 'ttl=20');
$capability->allowClientOutgoing($TWILIO_TWIML_APP_SID);
$token = $capability->generateToken();
I think this is all fairly standard stuff from the quickstart files. I only had a quick go with it, but I don't remember it being complicated. Have fun!

Resources