Twilio Autopilot - sourceChannel - twilio-api

Is there a way to check the source channel (ie Alexa vs Programmable Chat) in the functions to direct to different answers depending on the source? I found some sourceChannel references in the docs, but I couldn't figure out how to reference those properties in a function.
https://www.twilio.com/docs/autopilot/api/query#query-properties

If you use Twilio functions behind your Autopilot task, it is possible.
In the event parameter you'll find the channel.
Eg. Checking if facebook else Whatsapp
exports.handler = function(context, event, callback) {
let channel = "";
if(event.Channel == "messageing.facebook-messenger"){
channel = "Facebook";
}else{
channel = "Whatsapp";
}
responseObject = {
"actions": [
{
"say": `Your channel is ${channel}`
}
]
};
return callback(null, responseObject);
}

Related

How to call external API with parameters from the Twilio function

I am trying to write one Twilio function. Inside the Twilio function, I have one external API call with parameters for one of my API. API will return the result and that result I am passing using "Say" tag.
I have one Twilio Autopilot Bot in which I have one task added. On execution of that task it will call "Action URL" which is the Twilio function URL.
But somehow this full flow is not working. I think my external API call using AXIOS is not proper. Can you help me to call external API with parameters from the Twilio function? For my Twilio function check following code
Thanks in advance
exports.handler = function(context, event, callback) {
const responseData = await axios.post(`API_PATH/GetMessageData`,'Minute':'3000','MessageType':'2,3'});
const resultData = responseData.data;
let response = {};
response.actions = [];
response.actions.push({"say":"hello sam" + resultData})
callback(null,response)
};
You are calling axios using await, but you have not declared the function to be an async function.
You should also ensure to catch any potential API or connectivity errors when making external requests. That will also show if there's an error in calling your API.
exports.handler = async function(context, event, callback) {
try {
const responseData = await axios.post(`API_PATH/GetMessageData`,'Minute':'3000','MessageType':'2,3'});
const resultData = responseData.data;
let response = {};
response.actions = [];
response.actions.push({"say":"hello sam" + resultData})
callback(null,response)
} catch(error) {
console.error(error)
let response = {};
response.actions = [];
response.actions.push({"say":"There was a problem with the bot, please try again."});
callback(null, response);
}
};
Edit
You also added that your result looks like this:
{
"Message": {
"Text": "Data retrieved successfully"
},
"MessageList": [
{ "ContactNo": "+91xxxxxxxx", "Message": "test message", },
{ "ContactNo": "+91xxxxxxxx", "Message": "test message 2", }
]
}
I'm not sure exactly which of those messages are what you want to send back to the user. Perhaps you want to send both of the Messages inside the MessageList object? You could do that like so (just showing the part of the code inside the try):
const responseData = await axios.post(`API_PATH/GetMessageData`,'Minute':'3000','MessageType':'2,3'});
const resultData = responseData.data;
let response = {};
response.actions = [];
resultData.MessageList.forEach((message) => {
response.actions.push({"say": message.Message });
}
callback(null,response)
This loops through the MessageList and adds a new say action to the response with each message.

bot responds to specific channel discord.js

How do I get a bot to respond only to a specific channel where I write a command
client.on('message', message => {
if(message.content.startsWith("hey")) {
message.channel.send('hello');
}
});
A simple approach is to check message.channel.name against the name of the authorized channel or list of channels. For example if (message.channel.name === "BotLounge"). For other information available about the channel please see https://discord.com/developers/docs/resources/channel
You can use message.channel.id because the channel has a unique id, or you can check with message.channel.name but this is less unique, and you can have troubles with it.
Sou you can do something like:
const myChannelId = '0123456789'
client.on('message', message => {
if(message.channel.id === myChannelId) return;
if(message.content.startsWith("hey")) {
message.channel.send('hello');
}
});

I want to trigger mail when the bot says that it has no answer

I want to trigger mail when the bot says that it has no answer.
I'm using MS bot framework SDk4, and using LUIS and QnA maker also, when the bot reached the to a point where it says that it has no answer , we want a mail to be triggered or add a new item in the sharepoint
If you want to add a no answer to a SharePoint List, I managed to get it working using the csom-node package and Bot Framework v4 / NodeJS. Granted, it's not the most elegant solution, but it works.
Bot.JS
const csomapi = require('../node_modules/csom-node');
settings = require('../settings').settings;
// Set CSOM settings
csomapi.setLoaderOptions({url: settings.siteurl});
Bit further down the page...
// If no answers were returned from QnA Maker, reply with help.
} else {
await context.sendActivity("Er sorry, I don't seem to have an answer.");
console.log(context.activity.text);
var response = context.activity.text;
var authCtx = new AuthenticationContext(settings.siteurl);
authCtx.acquireTokenForApp(settings.clientId, settings.clientSecret, function (err, data) {
var ctx = new SP.ClientContext("/sites/yoursite"); //set root web
authCtx.setAuthenticationCookie(ctx); //authenticate
var web = ctx.get_web();
var list = web.get_lists().getByTitle('YourList');
var creationInfo = new SP.ListItemCreationInformation();
var listItem = list.addItem(creationInfo);
listItem.set_item('Title', response);
listItem.update();
ctx.load(listItem);
ctx.executeQueryAsync();
});
}
Proactive Messaging doesn't really work for email (to prevent spam), so you're better off not using the Bot Framework SDK for the email portion. #Baruch's link, How to send email in ASP.NET C# is good if you're using the C# SDK. Here's one for sending emails in Node.
All you have to do is send the email when QnA Maker doesn't return any results. In this sample, you would do so here:
if (response != null && response.Length > 0)
{
await turnContext.SendActivityAsync(MessageFactory.Text(response[0].Answer), cancellationToken);
}
else
{
await turnContext.SendActivityAsync(MessageFactory.Text("No QnA Maker answers were found."), cancellationToken);
// Add code that sends Notification Email
}
That being said, if you'd like to try a semi-proactive route, you can enable the Email Channel in your bot, then use this:
if (response != null && response.Length > 0)
{
await turnContext.SendActivityAsync(MessageFactory.Text(response[0].Answer), cancellationToken);
}
else
{
await turnContext.SendActivityAsync(MessageFactory.Text("No QnA Maker answers were found."), cancellationToken);
MicrosoftAppCredentials.TrustServiceUrl(#"https://email.botframework.com/", DateTime.MaxValue);
var user = new ChannelAccount(name: "MyUser", id: "<notified Email Address>");
var parameters = new ConversationParameters()
{
Members = new ChannelAccount[] { user },
Bot = turnContext.Activity.Recipient
};
var connector = new ConnectorClient(new Uri("https://email.botframework.com"), "<appId>", "<appPassword>");
var conversation = await connector.Conversations.CreateConversationAsync(parameters);
var activity = MessageFactory.Text("This is a notification email");
activity.From = parameters.Bot;
activity.Recipient = user;
await connector.Conversations.SendToConversationAsync(conversation.Id, activity);
}
The catch is that <notified Email Address> has to send a message to the bot before any notifications will work. If it doesn't, it will return a 401: Unauthorized error. Again, I don't recommend this route.
Note: If you're using the Dispatch sample, you'd place the code here:
private async Task ProcessSampleQnAAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
_logger.LogInformation("ProcessSampleQnAAsync");
var results = await _botServices.SampleQnA.GetAnswersAsync(turnContext);
if (results.Any())
{
await turnContext.SendActivityAsync(MessageFactory.Text(results.First().Answer), cancellationToken);
}
else
{
// PLACE IT HERE
await turnContext.SendActivityAsync(MessageFactory.Text("Sorry, could not find an answer in the Q and A system."), cancellationToken);
}
}

xamarin forms: Calling phone and sending email (IOS, Android and UWP)

Currently using following code for calling and email features, but it is only working in Android and not working in IOS. Also, I need these features in UWP.
For call:
string phoneno = "1234567890";
Device.OpenUri(new Uri("tel:" + phoneno));
For mail:
string email = "sreejithsree139#gmail.com";
Device.OpenUri(new Uri("mailto:" + email ));
Any package available for this?
Xamarin.Essentials (Nuget) is available as a preview package and contains functionality to both open the default mail app and attach information such as the recipients, subject and the body as well as open the phone dialer with a certain number.
There is also a blog post about Xamarin.Essentials available on blog.xamarin.com.
Edit:
As for your mail issue, Xamarin.Essentials expects an array of strings as recipients so you are able to send mail to multiple people at once. Just pass a string array with one single value.
var recipients = new string[1] {"me#watercod.es"};
If you're using the overload that expects an EmailMessage instance, you are supposed to pass a List of string objects.
In that case, the following should work:
var recipients = new List<string> {"me#watercod.es"};
Updating the complete code for calling and mailing features using Xamarin.Essentials, this might help others.
For call:
try
{
PhoneDialer.Open(number);
}
catch (ArgumentNullException anEx)
{
// Number was null or white space
}
catch (FeatureNotSupportedException ex)
{
// Phone Dialer is not supported on this device.
}
catch (Exception ex)
{
// Other error has occurred.
}
For Mail:
List<string> recipients = new List<string>();
string useremail = email.Text;
recipients.Add(useremail);
try
{
var message = new EmailMessage
{
//Subject = subject,
//Body = body,
To = recipients
//Cc = ccRecipients,
//Bcc = bccRecipients
};
await Email.ComposeAsync(message);
}
catch (Exception ex)
{
Debug.WriteLine("Exception:>>"+ex);
}
Hello to make a call in UWP:
if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.ApplicationModel.Calls.PhoneCallManager"))
{
Windows.ApplicationModel.Calls.PhoneCallManager.ShowPhoneCallUI("123", "name to call");
}
To send a Text:
private async void ComposeSms(Windows.ApplicationModel.Contacts.Contact recipient,
string messageBody,
StorageFile attachmentFile,
string mimeType)
{
var chatMessage = new Windows.ApplicationModel.Chat.ChatMessage();
chatMessage.Body = messageBody;
if (attachmentFile != null)
{
var stream = Windows.Storage.Streams.RandomAccessStreamReference.CreateFromFile(attachmentFile);
var attachment = new Windows.ApplicationModel.Chat.ChatMessageAttachment(
mimeType,
stream);
chatMessage.Attachments.Add(attachment);
}
var phone = recipient.Phones.FirstOrDefault<Windows.ApplicationModel.Contacts.ContactPhone>();
if (phone != null)
{
chatMessage.Recipients.Add(phone.Number);
}
await Windows.ApplicationModel.Chat.ChatMessageManager.ShowComposeSmsMessageAsync(chatMessage);
}
as found in Microsoft documentation here: Compose SMS documentation
==> So you can make (If not already done) a shared service interface in your Xamarin app, then the implementation with these codes in your UWP app...
To send an email:
To send an email in UWP, you can refer to the Microsoft documentation too:
Send Email documentation (UWP)
Using a plugin
Else you can use a Xamarin plugin:
documentation: Xamarin cross messaging plugin
Nuget: Nuget plugin package
In our app, we are doing the phone calling with a DependencyService.
Therefore in our PCL, we have
public interface IPhoneCall
{
void Call(string number);
}
On the iOS side, the following method does the calling:
public void Call(string number)
{
if (string.IsNullOrEmpty(number))
return;
var url = new NSUrl("tel:" + number);
if (!UIApplication.SharedApplication.OpenUrl(url))
{
var av = new UIAlertView("Error",
"Your device does not support calls",
null,
Keys.Messages.BUTTON_OK,
null);
av.Show();
}
}
If don't want to wait for the Xamarin essentials that is still in pre-release as of today, you can use this open source plugin. It works on iOS, Android and UWP. There is a sample from the github documentation :
// Make Phone Call
var phoneDialer = CrossMessaging.Current.PhoneDialer;
if (phoneDialer.CanMakePhoneCall)
phoneDialer.MakePhoneCall("+27219333000");
// Send Sms
var smsMessenger = CrossMessaging.Current.SmsMessenger;
if (smsMessenger.CanSendSms)
smsMessenger.SendSms("+27213894839493", "Well hello there from Xam.Messaging.Plugin");
var emailMessenger = CrossMessaging.Current.EmailMessenger;
if (emailMessenger.CanSendEmail)
{
// Send simple e-mail to single receiver without attachments, bcc, cc etc.
emailMessenger.SendEmail("to.plugins#xamarin.com", "Xamarin Messaging Plugin", "Well hello there from Xam.Messaging.Plugin");
// Alternatively use EmailBuilder fluent interface to construct more complex e-mail with multiple recipients, bcc, attachments etc.
var email = new EmailMessageBuilder()
.To("to.plugins#xamarin.com")
.Cc("cc.plugins#xamarin.com")
.Bcc(new[] { "bcc1.plugins#xamarin.com", "bcc2.plugins#xamarin.com" })
.Subject("Xamarin Messaging Plugin")
.Body("Well hello there from Xam.Messaging.Plugin")
.Build();
emailMessenger.SendEmail(email);
}

Apigee push notification - one

Apigee's push notification is documented here.
http://apigee.com/docs/api-baas/content/introducing-push-notifications
I tried this with the js sdk that Apigee provides here http://apigee.com/docs/app-services/content/installing-apigee-sdk-javascript. It looks like only the client can generate a notification to itself?
But I have a scenario where I would like to push notifications to multiple clients from a nodejs job that runs once every hour. Something like this, but from the nodejs sdk not from the js sdk.
var devicePath = "devices;ql=*/notifications";
How do I do this?
As remus points out above, you can do this with the usergrid module (https://www.npmjs.com/package/usergrid).
You are basically trying to construct an API call that looks like this (sending a message by referencing a device):
https://api.usergrid.com/myorg/myapp/devices/deviceUUID/notifications?access_token= access_token_goes_here '{"payloads":{"androidDev":"Hello World!!"}}'
Or like this (sending a message by referencing a user who is connected to a device)
https://api.usergrid.com/myorg/myapp/users/fred/notifications?access_token=access_token_goes_here '{"payloads":{"androidDev":"Hello World!!"}}'
You can do this with code that looks something like this:
var options = {
method:'POST',
endpoint:'devices/deviceUUID/notifications',
body:{ 'payloads':{'androidDev':'Hello World!!'} }
};
client.request(options, function (err, data) {
if (err) {
//error - POST failed
} else {
//data will contain raw results from API call
//success - POST worked
}
});
or
var options = {
method:'POST',
endpoint:'users/fred/notifications',
body:{ 'payloads':{'androidDev':'Hello World!!'} }
};
client.request(options, function (err, data) {
if (err) {
//error - POST failed
} else {
//data will contain raw results from API call
//success - POST worked
}
});
Note: the second call, that posts to the users/username/notifications endpoint assumes that you have already made a connection between the user and their device (e.g. POST /users/fred/devices/deviceUUID).