Twilio check if phone number has been blacklisted - ruby-on-rails

I am currently integrating into the twilio rest api and need to perform a check on a users phone number to determine if that user has blacklisted themselves or not. I have little experience with this api and scouring through the documentation and google has turned up nothing.
In our application we are going to have a notification center and if the user has blacklisted themselves I do not want to give them the ability to turn on their SMS notifications. Potentially a user could have SMS notifications on but twilio would block any messages. I know there is the ability to get a status code back from twilio when an SMS is queued that shows the user is blacklisted (https://www.twilio.com/docs/api/rest/message). However, I will not be sending messages on the notifications screen and need a direct way (if at all possible) to check twilio to determine if a number is blacklisted. Any help is much appreciated. Let me know if anymore information will be of help.

Megan from Twilio.
I'd be curious to see if you ever tried your own workaround. But I wanted to note for others in a similar situation how you could grab the blacklist error and then do whatever you may want with it.
In Ruby it would look something like this:
require 'rubygems'
require 'twilio-ruby'
account_sid = 'YOUR_ACCOUNT_SID'
auth_token = 'YOUR_AUTH_TOKEN'
#client = Twilio::REST::Client.new account_sid, auth_token
begin
#message = #client.messages.create(
from: 'TWILIO_NUMBER',
to: 'USER_NUMBER',
body: 'Howdy!'
)
rescue Twilio::REST::RestError => e
if e.code == 21610
# User is blacklisted
# Store info however you choose
puts e.message
end
end
We check for blacklisting specifically using the code '21610'. For more information about errors you can visit the reference page.
Hope this helps!

Twilio recommends developers to store the opt-out/in statuses in their side. I have stored it in DB. There are 2 ways to collect the unsubscribed users list.
1) Use SMS webhooks. You can find how to configure your Twilio number to receive webhook events here
#PostMapping(value = "/twilio", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_ATOM_XML_VALUE)
public String twilioConsumer(TwilioEventDTO twilioEventDTO) {
// twilioEventDTO.getBody() => returns the body of the SMS user replied.
twilioService.consume(twilioEventDTO);
return new MessagingResponse.Builder().build().toXml();
}
2) Since I implemented webhooks later, I had to collect already unsubscribed users. When you send sms to the number that has been opted-out, Twilio API throws an exception with the status number of 21610. You can catch it and store the number in DB.
try {
Message result = Message.creator(
new PhoneNumber(toPhoneNumber),
new PhoneNumber(fromPhoneNumber),
messageBody)
.create();
response = result.getStatus().name();
} catch (ApiException e) {
if (e.getCode().equals(21610))
updateSubscription(toPhoneNumber, false);
logger.warn("Error on sending SMS: {}", e.getMessage());
}
P.S.: examples written in Java - Spring Boot framework.

Related

Output from Studio Flow via API not being sent to website callback

We are trying to implement a chatbot on our website.
My code successfully triggers the Flow. The Conversations log on Twilio shows that my code sent a message of "Hi" and the Flow triggered and sent the expected greeting.
The problem is that I'm not seeing anyplace where the Flow output is being sent to my website callback and so I'm not able to output the Flow messages to my website user.
When the Flow sends a message, where is the configuration that makes a callback to my website so I can output the message to the user?
onMessageAdded DOES get called on my website callback, but only for messages sent by the website code - not the Flow.
At this point I think the problem is a Twilio configuration for Conversations, Messages or the Flow, but it could be a configuration problem in my code.
Here is my rough initial code:
TwilioClient.Init(_twilioAccountSid, _twilioAuthToken);
//
// Create Conversation
var conversation = ConversationResource.Create(
friendlyName: "Test conversation",
messagingServiceSid: _twilioMessagingServiceSid,
attributes: null,
xTwilioWebhookEnabled: ConversationResource.WebhookEnabledTypeEnum.True
);
_log.Info("Conversation.Create: " + conversation.Sid);
//
// Attach Flow to Conversation
var webhook = WebhookResource.Create(
configurationMethod: WebhookResource.MethodEnum.Post,
configurationFlowSid: _twilioStudioFlowSid,
target: WebhookResource.TargetEnum.Studio,
configurationFilters: new List<string> {
"onMessageAdded",
"onMessageUpdated",
"onMessageRemoved",
"onConversationUpdated",
"onConversationRemoved",
"onParticipantAdded",
"onParticipantUpdated",
"onParticipantRemoved"
},
pathConversationSid: conversation.Sid
);
_log.Info("WebhookResource.Create: " + webhook.Sid);
//
// Create a Participant
var participant = ParticipantResource.Create(
identity: _identity,
pathConversationSid: conversation.Sid
);
_log.Info("Participant.Create: " + participant.Sid);
//
// Send Message
var message = MessageResource.Create(
author: _identity,
body: "Hi!",
xTwilioWebhookEnabled: MessageResource.WebhookEnabledTypeEnum.True,
pathConversationSid: conversation.Sid
);
_log.Info("Message.Create: " + message.Sid);
Is there a reason you decided to not use the Twilio Conversations SDK for JavaScript?
The architecture you are using may require this additional configuration.
Triggering Webhooks for REST API Events
Upon configuration, only actions from SDK-driven clients (like mobile phones or browsers) or SMS-based Participants will cause webhooks without further action on your part. This includes both Service-level webhooks and Conversation-Scoped Webhooks. This is a default behavior to help avoid infinite feedback loops.
Your Post-Event Webhook target, however, may be an important tool for archiving. In this case, you may also want to enable webhook "echoes" from actions you take on the REST API. To do so, you can add a header X-Twilio-Webhook-Enabled=true to any such request. Requests bearing this header will yield webhooks to the configured Post-Event webhook target.
Troubleshooting Webhook Delivery for Conversations or Chat
I don’t think there is a way to set this header when using Twilio Studio widgets.

Identifying users in Rails Web push notifications

I'm developing a Rails application, and I'd like to send web push notifications to specific users when certain actions happen, e.g:
A user started tracking a timer, but the timer has been running for more than 6 hours. Then the app sends that user a web notification.
I've been doing research and found this tutorial, the author implements push notifications for Rails, however there's no insight on how to identify the users.
From what I understood, the users needs to subscribe from their browser to be able to get push notifications, however, considering each user can use the application from multiple browsers, how can I automatically subscribe/unsubscribe a user for notifications in all browsers they use the app from?
So, what I did was adding a notification_subscription model to my User model.
On my javascript, I check if there's a current browser subscription present:
this.serviceWorkerReady()
.then((serviceWorkerRegistration) => {
serviceWorkerRegistration.pushManager.getSubscription()
.then((pushSubscription) => {
if (pushSubscription && _.includes(subscriptionEndpoints, pushSubscription.endpoint)) {
return;
}
this.subscribe();
});
});
I check if the current subscription is already present in the user stored endpoints, and subscribe if it isn't.
On subscription I send the new endpoint to the backend, which adds the new subscription to the user:
$.post(Routes.users_subscriptions_path({ format: 'json' }), {
subscription: subscription.toJSON()
});
Then I can send notifications to users to every endpoint:
def push_notifications_to_user(user)
message = {
title: "A message!",
tag: 'notification-tag'
}
user.notification_subscriptions.each do |subscription|
begin
Webpush.payload_send(
message: JSON.generate(message),
endpoint: endpoint,
p256dh: p256dh,
auth: auth,
api_key: public_key
)
rescue Webpush::InvalidSubscription => exception
subscription.destroy
end
end
end
The webpush gem raises an InvalidSubscription exception if the endpoint is invalid, we can destroy that endpoint to keep only the valid endpoints from the user.
The endpoint is unique by browser so you need an additional authentication scheme on the top of your app to send user's information along with the new endpoint.
You need to attach metadata (i.e. the user ID) to the endpoint when you store it on your server:
#subscription = Subscriptions.new endpoint: params[:endpoint]
#subscription.user = current_user
// or if you send with AJAX the user id together with the endpoint
#subscription.user = User.find params[:user_id]
In the second case I suggest to sign the user ID or use a secret token, otherwise anyone would be able to subscribe to push notifications as if it was another user.
Then you can delete from the database all the endpoints that belong to that user ID to unsubscribe all his devices.
However I don't think it's a good practice: a user may want to receive notifications on a device and not on another one.

Twilio Complications

I'm currently trying to use Twilio with my Thingworx platform to send sms messages when a sensor becomes triggered.
When I set the sensor to an active triggered state, the sms messages then spam me and do not turn off until i set it to a false manually.
Is there a script that can turn a twilio sms to false, or a reason why it is spamming me?
Thank you
The code sending sms should look something like this:
https://www.twilio.com/docs/api/rest/sending-messages
from twilio.rest import TwilioRestClient
# put your own credentials here
ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
AUTH_TOKEN = "your_auth_token"
client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN)
client.messages.create(
to="+15558675309",
from_="+15017250604",
body="This is the ship that made the Kessel Run in fourteen parsecs?",
media_url="https://c1.staticflickr.com/3/2899/14341091933_1e92e62d12_b.jpg",
)
It is likely as Phil stated above, that you were checking the sensor as part of a loop and just sending every time.

StatusCallback does not work as expected

Overview:
I am working on a VB.NET application that places a call into Twilio, the number is not a test number. I am using the C# library with the code written in VB.Net.
When I use this line of code:
Console.WriteLine(account.SendSmsMessage(Caller, to1, strBody))
I receive a text message on my phone however the post back is never posted to my website. I have included the URL of the site on the account under Messaging > Request URL.
When I reply to the message, Twilio does make a post to my site. From what I understand, a POST should have been made when Twilio was first sent a message from my application, however this is not the case.
When using this code, I do not get any text message and no POST is made.
Console.WriteLine(account.SendMessage(Caller, to1, strBody, PostBackURL))
I have tried SendSMSMessage, I have tried it with the URL on my account and without it,
nothing seems to effect the behavior.
I need the SmsMessageSid at the time the message is sent. From everything I have seen, Twilio does not provide a response other then what is sent to the PostBackURL, I could parse a response for the
SmsMessageSid however since there is no response that is not an option. If I am mistaken on that point that would be great, however it looks like the only way to get a reply is with the post back URL. Thanks for your help with this! Below you will find an excerpt of the code I am working with:
PostBackURL = "http%3A%2F%2F173.111.111.110%3A8001/XMLResponse.aspx"
' Create Twilio REST account object using Twilio account ID and token
account = New Twilio.TwilioRestClient(SID, Token)
message = New Twilio.Message
Try
'WORKS
'Console.WriteLine(account.SendSmsMessage(Caller, to1, strBody))
'DOES NOT WORK
Console.WriteLine(account.SendMessage(Caller, to1, strBody, PostBackURL))
Catch e As Exception
Console.WriteLine("An error occurred: {0}", e.Message)
End Try
Console.WriteLine("Press any key to continue")
Console.ReadKey()
I'm doing something similar with C# and like you, I'm not getting the POST to the callback URL. I don't know why that's not working, but if all you need is the sid when you send the message, you should be able to do this:
message = SendSmsMessage(Caller, to1, strBody))
and message.Sid will give you what you need, assuming no exceptions.

Instead of using two different phone numbers for a Twilio Queue, could I use one phone for users and the browser client for support reps?

I’m building a queue. I have one phone line, intended for users calling customer support, configured with a Voice URL of example.com/caller. That address returns TwiML that queues the call:
post '/caller' do
response = Twilio::TwiML::Response.new do |r|
r.Say "Welcome to Support, please hold!"
r.Enqueue 'Support Queue'
end
response.text
end
According to the official call queue example I need another phone line for customer support agents to call, that returns TwiML that dequeues a user in the queue. Is it possible for agents instead dequeue users using the browser client instead? Why doesn't this code work?
get '/'
capability = Twilio::Util::Capability.new account_sid, auth_token
# the TwiML app friendly-named 'Agent' has a voice URL set to example.com/agent
capability.allow_client_outgoing 'Agent'
token = capability.generate
erb :support, locals: { token: token }
end
post '/agent' do
response = Twilio::TwiML::Response.new do |r|
r.Dial do |d|
d.Queue 'Support Queue'
end
end
response.text
end
The actual error is that when I make a call from my browser using Twilio.Device.connect() the call hangs up immediately instead of connecting to the user in the queue.
Twilio evangelist here.
I think you need to change the value of the allow_client_outgoing parameter to a TwiML Application SID, which you can create in your account portal or via the REST API. This SID is what lets Twilio know what URL you want us to request when the instance of Client connects to Twilio.
Also, we recently released a new product called TaskRouter which will automatically route queued calls to an available agent, so you not longer have to have an agent dial into the Queue in order to get calls from it.
Hope that helps.

Resources