Twilio TaskRouter - Accepting a reservation from the JS client - javascript

I am using the Taskrouter js library, more specifically the worker.js.
this.worker.on("reservation.created", (reservation) => {
reservation.accept()
});
However, I am getting an error saying that
accept() is not a function
According to the documentation here: https://www.twilio.com/docs/api/taskrouter/worker-js
This will accept the reservation for the worker.
Note: This will NOT perform any telephony. If the task was enqueued
using the Enqueue TwiML verb, utilize
reservation.dequeue(#reservation-dequeue) to perform telephony and
dequeue the call.
reservation.accept(
function(error, reservation) {
if(error) {
console.log(error.code);
console.log(error.message);
return;
}
console.log("reservation accepted");
for (var property in reservation) {
console.log(property+" : "+reservation[property]);
}
}
);
So we I am confused as reservation has no function accept(), but according to the documentation it does... So how do I accept a reservation from js?

Why do you have this.worker.on?
https://www.twilio.com/docs/api/taskrouter/worker-js#example_6
worker.on("reservation.created", function(reservation) {
console.log(reservation.task.attributes) // {foo: 'bar', baz: 'bang' }
console.log(reservation.task.priority) // 1
console.log(reservation.task.age) // 300
console.log(reservation.task.sid) // WTxxx
console.log(reservation.sid) // WRxxx
});

Related

VueJS access to a variable from another method [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 1 year ago.
I'm using Vuejs and i would i have two methods one is to make a call and another one is to hangup
i would like to access to device variable that i have in makeCall methods from hangup
error : Cannot set property 'device' of undefined at eval
this is my code :
export default {
components: {Modal},
data: () => ({
device: '',
showModal: false,
form:{
output: ''
},
collection: {
}
}),
created(){
},
methods: {
init(){
this.showModal = true
},
dialer(digit){
this.form.output += `${digit}`
this.count++
},
clearScreen(){
let screen = document.getElementById('output').value
this.form.output = screen.slice(0, -1)
},
hangUp(){
this.device.disconnectAll();
},
makeCall(){
console.log("Requesting Access Token...");
// Using a relative link to access the Voice Token function
getAPI.get("api/contacts/token/")
.then(function (response) {
console.log("Got a token.");
console.log("Token: " + response.data.token);
// Setup Twilio.Device
this.device = new Twilio.Device(response.data.token, {
// Set Opus as our preferred codec. Opus generally performs better, requiring less bandwidth and
// providing better audio quality in restrained network conditions. Opus will be default in 2.0.
codecPreferences: ["opus", "pcmu"],
// Use fake DTMF tones client-side. Real tones are still sent to the other end of the call,
// but the client-side DTMF tones are fake. This prevents the local mic capturing the DTMF tone
// a second time and sending the tone twice. This will be default in 2.0.
fakeLocalDTMF: true,
// Use `enableRingingState` to enable the device to emit the `ringing`
// state. The TwiML backend also needs to have the attribute
// `answerOnBridge` also set to true in the `Dial` verb. This option
// changes the behavior of the SDK to consider a call `ringing` starting
// from the connection to the TwiML backend to when the recipient of
// the `Dial` verb answers.
enableRingingState: true,
debug: true,
});
this.device.on("ready", function (device) {
console.log("Twilio.Device Ready!");
});
this.device.on("error", function (error) {
console.log("Twilio.Device Error: " + error.message);
});
this.device.on("connect", function (conn) {
console.log('Successfully established call ! ');
// $('#modal-call-in-progress').modal('show')
});
this.device.on("disconnect", function (conn) {
console.log("Call ended.");
// $('.modal').modal('hide')
});
var params = {
To: document.getElementById('output').value
};
console.log("Calling me " + document.getElementById('output').value + "...");
if (this.device) {
var outgoingConnection = this.device.connect(params);
outgoingConnection.on("ringing", function () {
console.log("Ringing...");
});
}
})
.catch(function (err) {
console.log(err);
console.log("Could not get a token from server!");
});
}
}
}
</script>
The error was due to how this works in JS. The function declaration in the promise was creating a different this context than the main function. The function keyword sets this based on where it is called, whereas arrow functions set this based on where it is defined in the code.
All you need to do is replace the function(response){} declaration in the getAPI promise .then with an arrow function, and it will work fine.
makeCall(){
console.log("Requesting Access Token...");
// Using a relative link to access the Voice Token function
getAPI.get("api/contacts/token/")
.then((response) => {
Try replacing these lines - to use an arrow function in the .then

Twitter authentication in Codebird JS

I am very new to integrating social sites into a website. I somewhat managed to integrate Facebook, but I have no idea how to integrate Twitter.
I want to login through a Twitter account, then get the username and some other data from Twitter. I have a consumer key and consumer secret. I'm not sure how to proceed from here, and my Google searches haven't helped so far.
I am trying with codebird js:
$(function() {
$('#twitter').click(function(e) {
e.preventDefault();
var cb = new Codebird;
cb.setConsumerKey("redacted", "redacted");
cb.__call(
"oauth_requestToken",
{ oauth_callback: "http://127.0.0.1:49479/" },
function (reply, rate, err) {
if (err) {
console.log("error response or timeout exceeded" + err.error);
}
if (reply) {
// stores it
cb.setToken(reply.oauth_token, reply.oauth_token_secret);
// gets the authorize screen URL
cb.__call(
"oauth_authorize",
{},
function (auth_url) {
window.codebird_auth = window.open(auth_url);
}
);
}
}
);
cb.__call(
"account_verifyCredentials",
{},
function(reply) {
console.log(reply);
}
);
})
});
But I get
Your credentials do not allow access to this resource
How can I resolve this and get the user data? I am open to using an alternate Twitter implementation.
You cannot call cb._call( "account_verifyCredentials"... there.
The code only has a request token, NOT an access token, which you will only receive after the user authorizes your app (on the Twitter auth popup).
You are using the "callback URL without PIN" method, as documented on the README. So you'll need to implement that example code on your http://127.0.0.1:49479/ page.
Also, this essentially requires that you store the oauth credentials somewhere. In my example below, I've used localStorage.
$(function () {
$('#twitter').click(function (e) {
e.preventDefault();
var cb = new Codebird;
cb.setConsumerKey("CeDhZjVa0d8W02gWuflPWQmmo", "YO4RI2UoinJ95sonHGnxtYt4XFtlAhIEyt89oJ8ZajClOyZhka");
var oauth_token = localStorage.getItem("oauth_token");
var oauth_token_secret = localStorage.getItem("oauth_token_secret");
if (oauth_token && oauth_token_secret) {
cb.setToken(oauth_token, oauth_token_secret);
} else {
cb.__call(
"oauth_requestToken", {
oauth_callback: "http://127.0.0.1:49479/"
},
function (reply, rate, err) {
if (err) {
console.log("error response or timeout exceeded" + err.error);
}
if (reply) {
console.log("reply", reply)
// stores it
cb.setToken(reply.oauth_token, reply.oauth_token_secret);
// save the token for the redirect (after user authorizes)
// we'll want to compare these values
localStorage.setItem("oauth_token", reply.oauth_token);
localStorage.setItem("oauth_token_secret", reply.oauth_token_secret);
// gets the authorize screen URL
cb.__call(
"oauth_authorize", {},
function (auth_url) {
console.log("auth_url", auth_url);
// JSFiddle doesn't open windows:
// window.open(auth_url);
$("#authorize").attr("href", auth_url);
// after user authorizes, user will be redirected to
// http://127.0.0.1:49479/?oauth_token=[some_token]&oauth_verifier=[some_verifier]
// then follow this section for coding that page:
// https://github.com/jublonet/codebird-js#authenticating-using-a-callback-url-without-pin
});
}
});
}
})
});
Also made a JSFiddle

jQuery undefined object error when initialisation code is skipped for some odd reason

I'am trying to run a Skype SDK on my site, which will allow me to log into Skype initially. The code I'am using is from https://msdn.microsoft.com/EN-US/library/dn962162(v=office.16).aspx but when running the javascript through it complains of an undefined object. Here is the javascript code (ignore the $j, this is needed by us to run jQuery),
/**
* This script demonstrates how to sign the user in and how to sign it out.
*/
$j(function () {
'use strict'; // create an instance of the Application object;
// note, that different instances of Application may
// represent different users
var Application
var client;
Skype.initialize({
apiKey: 'SWX-BUILD-SDK',
}, function (api) {
Application = api.application;
client = new Application();
}, function (err) {
alert('some error occurred: ' + err);
});
// whenever state changes, display its value
client.signInManager.state.changed(function (state) {
$j('#application_state').text(state);
});
// when the user clicks on the "Sign In" button
$j('#signin').click(function () {
// start signing in
client.signInManager.signIn({
username: $j('#username').text(),
password: $j('#password').text()
}).then(
//onSuccess callback
function () {
// when the sign in operation succeeds display the user name
alert('Signed in as ' + client.personsAndGroupsManager.mePerson.displayName());
},
//onFailure callback
function (error) {
// if something goes wrong in either of the steps above,
// display the error message
alert(error || 'Cannot sign in');
});
});
// when the user clicks on the "Sign Out" button
$j('#signout').click(function () {
// start signing out
client.signInManager.signOut()
.then(
//onSuccess callback
function () {
// and report the success
alert('Signed out');
},
//onFailure callback
function (error) {
// or a failure
alert(error || 'Cannot sign in');
});
});
});
When I run this through, it doesn't enter into the "Skype.initialize({" code but jumps to "client.signInManager.state.changed(function (state) {", which is when it throws this error "Uncaught TypeError: Cannot read property 'signInManager' of undefined". When running this though the source debugger in chrome it shows that "Application" is undefined and that "client" is also undefined. So my question is why aren't these 2 objects getting initialised in the Skype.initialize code?
You will have to add the listener, after the client is initialized. So in the initialize "success" callback. The way you have it implemented at the moment, the script tries to add the listener before the client is initialized, on an undefined object attribute, hence the error.

hapi.js best way to handle errors

I'm creating my first node.js REST web service using hapi.js. I'm curious as to the best way to handle errors let's say from my dao layer. Do i throw them in my dao layer and then just try/catch blocks to handle them and send back errors in my controller, or is there a better way that the cool kids are handling this?
routes/task.js
var taskController = require('../controllers/task');
//var taskValidate = require('../validate/task');
module.exports = function() {
return [
{
method: 'POST',
path: '/tasks/{id}',
config : {
handler: taskController.createTask//,
//validate : taskValidate.blah
}
}
]
}();
controllers/task.js
var taskDao = require('../dao/task');
module.exports = function() {
return {
/**
* Creates a task
*
* #param req
* #param reply
*/
createTask: function createTask(req, reply) {
taskDao.createTask(req.payload, function (err, data) {
// TODO: Properly handle errors in hapi
if (err) {
console.log(err);
}
reply(data);
});
}
}();
dao/task.js
module.exports = function() {
return {
createTask: function createTask(payload, callback) {
... Something here which creates the err variable...
if (err) {
console.log(err); // How to properly handle this bad boy
}
}
}();
Generic Solution w/ Fully Customisable Error Template/Messages
We wrote a Hapi Plugin that handles all errors seamlessly: npmjs.com/package/hapi-error
It lets you define your own custom error pages in 3 easy steps.
1. Install the plugin from npm:
npm install hapi-error --save
2. Include the plugin in your Hapi project
Include the plugin when you register your server:
server.register([require('hapi-error'), require('vision')], function (err) {
// your server code here ...
});
See: /example/server_example.js for simple example
3. Ensure that you have a View called error_template
Note: hapi-error plugin expects you are using Vision (the standard view rendering library for Hapi apps)
which allows you to use Handlebars, Jade, React, etc. for your templates.
Your error_template.html (or error_template.ext error_template.jsx) should make use of the 3 variables it will be passed:
errorTitle - the error tile generated by Hapi
statusCode - *HTTP statusCode sent to the client e.g: 404 (not found)
errorMessage - the human-friendly error message
for an example see: /example/error_template.html
That's it! Now your Hapi App handles all types of errors and you can throw your own custom ones too!
Note: hapi-error works for REST/APIs too. if the content type header (headers.acceps) is set to application/json then your app will return a JSON error to the client, otherwise an HTML page will be served.
In doing more research along with Ricardo Barros' comment on using Boom, here's what I ended up with.
controllers/task.js
var taskDao = require('../dao/task');
module.exports = function() {
return {
/**
* Creates a task
*
* #param req
* #param reply
*/
createTask: function createTask(req, reply) {
taskDao.createTask(req.payload, function (err, data) {
if (err) {
return reply(Boom.badImplementation(err));
}
return reply(data);
});
}
}();
dao/task.js
module.exports = function() {
return {
createTask: function createTask(payload, callback) {
//.. Something here which creates the variables err and myData ...
if (err) {
return callback(err);
}
//... If successful ...
callback(null, myData);
}
}();
I think the cool kids now use a package to caught unhandled errors with Hapi, I present to you, Poop.
The only thing Poop is missing is some rich documentation, but check it out, and you'll see that Poop is great.
Some of my friends went to a node.js event in Lisbon, on of the hosts was a guy in charge of web technology stack at Wallmart, they use Hapi.js, Poop and some other cool things.
So if they use poop it must be pretty awesome.
PS: The name is suppa awesome

Server side validation in Express compatible with a single page Angular application

I would like to perform server side validation, preferably with expressValidator. When saving a resource, I check to see if it is valid. If it's not valid what should I return?
There are examples:
http://blog.ijasoneverett.com/2013/04/form-validation-in-node-js-with-express-validator/
https://github.com/ctavan/express-validator
Unfortunately, I can't figure out my answer from that.
In Angular, I am using the $resource service. When I do a save, and there is a validation error, how should the server send this back? Note, this is a single page application.
Also, how should I handle this on the client side? Is this technically a success call?
Please, I am not looking for any instant, ajax, check per field solution. I want to submit save, if there is a problem, I would like to return the errors so that Angular can handle them. This does not need to be the perfect solution, just something to set me on the right track.
I am not handing the Angular code in an special way at the moment:
Controller:
$scope.saveTransaction = function (transaction) {
transactionData.saveTransaction(transaction);
}
Service
saveTransaction: function(transaction) {
return resource.save(transaction);
}
The server side code looks as follows:
app.post('/api/transactions', function (req, res) {
var transaction;
req.assert('amount', 'Enter an amount (numbers only with 2 decimal places, e.g. 25.50)').regex(/^\d+(\.\d{2})?$/);
var errors = req.validationErrors();
var mapped = req.validationErrors(true);
if (mapped) {console.log("MAPPED")};
//console.log(mapped);
if(!errors) {
console.log("Passed");
transaction = new TransactionModel({
date: req.body.date,
description: req.body.description,
amount: req.body.amount
});
transaction.save(function (err) {
if (!err) {
return console.log("created");
} else {
return console.log("err");
}
return res.send(transaction);
})
}
else {
console.log("Errors");
res.send(errors);
// res.render('Transaction', {
// title: 'Invalid Transaction',
// message: '',
// errors: errors
// });
}
});
You could send and handle "better" errors:
SERVER
res.json(500, errors)
CLIENT
resource.save(tran).then(function(){
//it worked
},
function(response) {
//it did not work...
//see response.data
});

Categories

Resources