I'm trying to see about using Twilio Serverless to replace my IVR. I would like to have some centralized functions to use within the functions.
For example, My main may be something like /MainMenu, which will have all the Twml.
but it will also need to call a function like /LogStats, which will be a function that does a REST Call to my API to collect Stats.
I'd appreciate your guidance in this. I'm also a little confused about why there's a Functions Classic, and a Functions Services. Am I to assume that Functions Classic will go away?
Thanks
Update from comments
Hi Lizzie, thanks for your response. I have it working with the zoltar example.. but when I try to use it for creating a call to a REST API, it's not consistently calling the API.. Any Ideas?
Here's what I'm talking about..
const axios = require('axios');
const log = {
ask: async function(event){
try{
const res = await axios.post('https://myid.ngrok.io/api/calllogger/lognewcall', {
CallSid: event.CallSid,
Caller: event.Caller,
App: "EmgLine",
CallerCity: event.CallerCity,
CallerState: event.CallerState
});
if(!res.ok){
throw new Error(`HTTP error! Status ${res.status}`);
}
const data = await res.Message;
return data;
} catch(err){
const errMessage = `test: ${err}`;
return errMessage;
}
}
};
module.exports = log;
Twilio developer evangelist here.
The Functions Classic are the older Functions with the older Functions UI. It still works, but Functions Services are newer and recommended to use. A Service is an application container to store all your Functions and Assets, and used to manage deployments and separate environments. You will likely create a new Service for each new project you work on.
You can use code from another Function in another Function with code like this
exports.handler = function (context, event, callback) {
// First, get the path for the Function. Note that the key of the function
// is not preceded by a "/" as is the case with Assets
const zoltarPath = Runtime.getFunctions()['zoltar'].path;
// Next, use require() to import the library
const zoltar = require(zoltarPath);
// Finally, use the module as you would any other!
console.log('The answer to your riddle is: ' + zoltar.ask());
return callback();
}
Let me know if this helps at all!
Related
What would be the equivalent in dart of the following javascript snippet?
myPeerConnection.createOffer().then(function(offer) {
return myPeerConnection.setLocalDescription(offer);
})
The straight translation:
final offer = await myPeerConnection.createOffer();
myPeerConnection.setLocalDescription(offer);
does not compile because createOffer() eventually returns a RtcSessionDescription and setLocalDescription accepts only a Map.
And RtcSessionDescription does not have a nice way to convert to a Map in the API.
Am I missing anything? Thanks!
After trying a few things, this works in my use case (at least in Chrome):
final offer = await myPeerConnection.createOffer();
myPeerConnection.setLocalDescription({"sdp": offer.sdp, "type": offer.type ?? 'offer'});
I'm a newbie in node.js(firebase functions) and Dialogflow fulfillment, I want to retrieve data in a different directory. first is to check the nearest store, and then check the inventory of the store in a different directory, but I have a problem with return. so how I can fix it?
app.intent('location_checking - yes',(conv)=> {
var store= database.ref('store');
var inventory = database.ref('inventory);
var keystore=[];
return store.orderByKey().on("child_added", function(snapshot){
keystore.push(snapshot.key)
})
return inventory.child(keystore).on("value", function(snapshot){
var tomato =snapshot.val().tomato;
//and then check the nearest store with available stock
})
})
You have a few issues, some of them conceptual.
The first is that you're using on() and the "child_added" event. But since this is happening inside an Intent Handler, which only gets triggered when the user has done something, you can't also listen to conventional events and react to them. Instead, you should probably use once() with a "value" event - so you query for the values you want and work with them.
Second is that the Intent Handler expects you to return a Promise if you are doing any asynchronous operations - anything that would require a callback handler, for example. This would require some restructuring in how you make the calls to once(), so they return a Promise, and you take action in a .then() block. Since you can chain Promises together using .then(), you can make multiple calls this way.
I'm not sure that ordering by key will get you the "closest" store, but I'll ignore that for the moment to illustrate the rest of the code.
So that part of your code might look something like
return store.orderByKey().once("value")
.then( snapshot => {
// Handle the results
// ...
// Make the next query
return inventory.child( childKey ).once("value");
})
.then( snapshot => {
// Handle the inventory results
});
You can also do this with async/await by making your Intent Handler an async function and then calling await on the database calls. Possibly something like.
app.intent('location_checking - yes', async (conv) => {
const store= database.ref('store');
const inventory = database.ref('inventory);
//...
const storeSnapshot = await store.orderByKey().once("value");
// Do something with the store snapshot
const inventorySnapshot = await inventory.child( childKey ).once("value");
// Do stuff with the inventory snapshot
})
My Twilio function is in danger of getting too large and unwieldy. I'd like to break it up into smaller functions, and have the 'master' function call the other functions to get data as needed.
I don't see anything in the documentation about this, and the few tests I've tried have not been successful. Is there an easy/best way to go about doing this? Thanks!
this is an example of how to include code from another function:
including function's body
exports.handler = function(context, event, callback) {
let path = Runtime.getFunctions().helper.path;
let helper = require(path);
let output = helper.output_init();
}
included function's body (the name of this function needs to be 'helper' to work on this example)
function output_init(){
let output = new Twilio.Response();
output.setStatusCode(200);
output.appendHeader('Content-Type', 'application/json');
return output;
}
module.exports ={
output_init: output_init,
};
hope this helps
there is a discussion around this topic on a Google Groups forum and the details are provided from the documentation below:
Runtime Client
https://www.twilio.com/docs/runtime/client#functions
"The Function object enables developers to compose complex applications by allowing them to include and execute code stored in multiple Functions."
I'm trying to write a library that will make it easer for dartisans to use the SoundCloud JavaScript SDK (http://developers.soundcloud.com/docs/api/sdks#javascript).
I'm using the 'dart:js' library, and
I'm only using one class to handle the proxy.
class SCproxy {
JsObject proxy = context['SC'];
String client_id;
SCproxy(this.client_id) {}
initialize() {
proxy.callMethod('initialize', [client_id]);
}
stream(String track_id){
var track = new JsObject(proxy.callMethod('stream',[track_id]));
print(track); // track should be the soundmanager2 object that we can call '.play' on.
}
The repo I'm hosting this from is (https://github.com/darkkiero/scproxy)
My problem occurs when I try to run my 'stream' method.
main() {
SCproxy SC = new SCproxy('Your SoundCloud API client_ID');
SC.initialize();
SC.stream('/tracks/111477464');
}
When I try to grab and use the soundmanager2 object returned by the javascript 'SC.stream' method, the dart editor gives me this exception :
Breaking on exception: type 'ScriptElement' is not a subtype of type 'JsFunction' of 'constructor'.
I am under the impression that I should be able to get the dart JsObject for the soundmanager2 object by collecting the callback of the 'SC.stream', But I'm not sure how.However I could be completely misusing 'dart:js' and that would be helpful information as well.
You don't seem to follow the SoundCloud JavaScript SDK documentation. Particularly for the stream method that takes a callback as parameter and doesn't return.
The following Dart code :
context['SC'].callMethod('stream', ['/tracks/293', (sound) {
sound.callMethod('play');
}]);
will do the same as this JS code :
SC.stream("/tracks/293", function(sound){
sound.play();
});
You can have a look at Using JavaScript from Dart for more explanations.
In Dart, there is a concept of Isolates. I have an application (that I'm experimenting in Dart) that has lots of asynchronous IO where each call (they are database calls) are dependent on the previous one. So I have ended up in a nested callback hell.
I was wondering if Isolates could solve that nested callback soup, but it looks a bit verbose and I'm not sure if it fits it well.
There are also Generators proposed in the next ECMAScript Harmony which could solve these things, but how would you currently do lots of asynchronous IO in Dart in a clean way?
You can use Future's and Completers to chain work together. The following future returns the result of a 'ls' command from a process:
Future<String> fetch(String dir) {
final completer = new Completer();
Process process = new Process.start('ls', [dir]);
process.exitHandler = (int exitCode) {
StringInputStream stringStream = new StringInputStream(process.stdout);
stringStream.dataHandler = () {
String content = stringStream.read();
completer.complete(content);
process.close();
};
};
process.errorHandler = (var error) {
completer.completeException(error);
return true;
};
return completer.future;
};
which you can then chain together like this:
fetch('/').then((val) => fetch("/usr").then((val) => fetch("/tmp")));
Not the most pretty solution but this is what I get by with now.