Masked Phone Numbers with Node.js and Express

Download the Code

This Express sample application is modeled after the amazing rental experience created by AirBnB, but with more Klingons.

Host users can offer rental properties which other guest users can reserve. The guest and the host can then anonymously communicate via a disposable Twilio phone number created just for a reservation. In this tutorial, we'll show you the key bits of code to make this work.

To run this sample app yourself, download the code and follow the instructions on GitHub.

Read how Lyft uses masked phone numbers to let customers securely contact drivers.

Create a Reservation

The first step in connecting a guest and host is creating a reservation. Here we handle a form submission for a new reservation which contains the message and the guest's information which is grabbed from the logged in user.

Loading Code Samples...
Language
var twilio = require('twilio');
var MessagingResponse = require('twilio').twiml.MessagingResponse;
var express = require('express');
var router = express.Router();
var Property = require('../models/property');
var Reservation = require('../models/reservation');
var User = require('../models/user');
var notifier = require('../lib/notifier');
var purchaser = require('../lib/purchaser');
var middleware = require('../lib/middleware');

router.get('/', middleware.isAuthenticated, function (req, res) {
  var userId = req.user.id;
  Reservation.find({})
  .deepPopulate('property property.owner guest')
  .then(function (reservations) {
    var hostReservations = reservations.filter(function (reservation) {
      return reservation.property.owner.id === userId;
    });

    res.render('reservations/index', { reservations: hostReservations, user: req.user });
  });
});

// POST: /reservations
router.post('/', function (req, res) {
  var propertyId = req.body.propertyId;
  var user = req.user;

  Property.findOne({ _id: propertyId })
  .then(function (property) {
    var reservation = new Reservation({
      message: req.body.message,
      property: propertyId,
      guest: user.id
    });

    return reservation.save();
  })
  .then(function () {
    notifier.sendNotification();
    res.redirect('/properties');
  })
  .catch(function(err) {
    console.log(err);
  });
});

// POST: /reservations/handle
router.post('/handle', twilio.webhook({validate: false}), function (req, res) {
  var from = req.body.From;
  var smsRequest = req.body.Body;

  var smsResponse;

  User.findOne({phoneNumber: from})
    .then(function (host) {
      return Reservation.findOne({status: 'pending'})
        .deepPopulate('property property.owner guest')
    })
    .then(function (reservation) {
      if (reservation === null) {
        throw 'No pending reservations';
      }

      var hostAreaCode = reservation.property.owner.areaCode;

      var phoneNumber = purchaser.purchase(hostAreaCode);
      var reservationPromise = Promise.resolve(reservation);

      return Promise.all([phoneNumber, reservationPromise]);
    })
    .then(function (data) {
      var phoneNumber = data[0];
      var reservation = data[1];

      if (isSmsRequestAccepted(smsRequest)) {
        reservation.status = "confirmed";
        reservation.phoneNumber = phoneNumber;
      } else {
        reservation.status = "rejected";
      }
      return reservation.save();
    })
    .then(function (reservation) {
      var message = "You have successfully " + reservation.status + " the reservation";
      respond(res, message);
    })
    .catch(function (err) {
      console.log(err);
      var message = "Sorry, it looks like you do not have any reservations to respond to";
      respond(res, message);
    });
});

var isSmsRequestAccepted = function (smsRequest) {
  return smsRequest.toLowerCase() === 'accept';
};

var respond = function(res, message) {
  var messagingResponse = new MessagingResponse();
  messagingResponse.message(message);

  res.type('text/xml');
  res.send(messagingResponse.toString());
}

module.exports = router;
routes/reservations.js
Create a Reservation

routes/reservations.js

Part of our reservation system is receiving reservation requests from potential renters. However, these reservations need to be confirmed. Let's see how we would handle this step.

Confirm the Reservation

Before the reservation is finalized, the host needs to confirm that the property was reserved. Learn how to automate this process in our first AirTNG tutorial, Workflow Automation.

Loading Code Samples...
Language
var twilio = require('twilio');
var MessagingResponse = require('twilio').twiml.MessagingResponse;
var express = require('express');
var router = express.Router();
var Property = require('../models/property');
var Reservation = require('../models/reservation');
var User = require('../models/user');
var notifier = require('../lib/notifier');
var purchaser = require('../lib/purchaser');
var middleware = require('../lib/middleware');

router.get('/', middleware.isAuthenticated, function (req, res) {
  var userId = req.user.id;
  Reservation.find({})
  .deepPopulate('property property.owner guest')
  .then(function (reservations) {
    var hostReservations = reservations.filter(function (reservation) {
      return reservation.property.owner.id === userId;
    });

    res.render('reservations/index', { reservations: hostReservations, user: req.user });
  });
});

// POST: /reservations
router.post('/', function (req, res) {
  var propertyId = req.body.propertyId;
  var user = req.user;

  Property.findOne({ _id: propertyId })
  .then(function (property) {
    var reservation = new Reservation({
      message: req.body.message,
      property: propertyId,
      guest: user.id
    });

    return reservation.save();
  })
  .then(function () {
    notifier.sendNotification();
    res.redirect('/properties');
  })
  .catch(function(err) {
    console.log(err);
  });
});

// POST: /reservations/handle
router.post('/handle', twilio.webhook({validate: false}), function (req, res) {
  var from = req.body.From;
  var smsRequest = req.body.Body;

  var smsResponse;

  User.findOne({phoneNumber: from})
    .then(function (host) {
      return Reservation.findOne({status: 'pending'})
        .deepPopulate('property property.owner guest')
    })
    .then(function (reservation) {
      if (reservation === null) {
        throw 'No pending reservations';
      }

      var hostAreaCode = reservation.property.owner.areaCode;

      var phoneNumber = purchaser.purchase(hostAreaCode);
      var reservationPromise = Promise.resolve(reservation);

      return Promise.all([phoneNumber, reservationPromise]);
    })
    .then(function (data) {
      var phoneNumber = data[0];
      var reservation = data[1];

      if (isSmsRequestAccepted(smsRequest)) {
        reservation.status = "confirmed";
        reservation.phoneNumber = phoneNumber;
      } else {
        reservation.status = "rejected";
      }
      return reservation.save();
    })
    .then(function (reservation) {
      var message = "You have successfully " + reservation.status + " the reservation";
      respond(res, message);
    })
    .catch(function (err) {
      console.log(err);
      var message = "Sorry, it looks like you do not have any reservations to respond to";
      respond(res, message);
    });
});

var isSmsRequestAccepted = function (smsRequest) {
  return smsRequest.toLowerCase() === 'accept';
};

var respond = function(res, message) {
  var messagingResponse = new MessagingResponse();
  messagingResponse.message(message);

  res.type('text/xml');
  res.send(messagingResponse.toString());
}

module.exports = router;
routes/reservations.js
Confirm the Reservation

routes/reservations.js

Once the reservation is confirmed, we need to purchase a Twilio number that the guest and host can use to communicate.

Purchase a Twilio Number

Here we use a Twilio Node Helper Library to search for and buy a new phone number to associate with the reservation. When we buy the number, we designate a Twilio Application that will handle webhook requests when the new number receives an incoming call or text.

We then save the new phone number on our reservation model, so when our app receives calls or texts to this number, we'll know which reservation the call or text belongs to.

Loading Code Samples...
Language
var config = require('../config');
var client = require('twilio')(config.accountSid, config.authToken);

var purchase = function (areaCode) {
  var phoneNumber;

  return client.availablePhoneNumbers('US').local.list({
        areaCode: areaCode,
        voiceEnabled: true,
        smsEnabled: true
  }).then(function(searchResults) {
    if (searchResults.availablePhoneNumbers.length === 0) {
      throw { message: 'No numbers found with that area code' };
    }

    return client.incomingPhoneNumbers.create({
      phoneNumber: searchResults.availablePhoneNumbers[0].phoneNumber,
      voiceApplicationSid: config.applicationSid,
      smsApplicationSid: config.applicationSid
    });
  }).then(function(number) {
    return number.phone_number;
  });
}

exports.purchase = purchase;
lib/purchaser.js
Purchase a Twilio Number

lib/purchaser.js

Now that each reservation has a Twilio Phone Number, we can see how the application will look up reservations as guest or host calls come in.

Find a Reservation

When someone sends an SMS or calls one of the Twilio numbers you have configured, Twilio makes a request to the URL you set in the Twiml app. In this request, Twilio includes some useful information including:

  • The From number that originally called or sent an SMS.
  • The To Twilio number that triggered this request.

Take a look at Twilio's SMS Documentation and Twilio's Voice Documentation for a full list of the parameters you can use.

In our controller we use the to parameter sent by Twilio to find a reservation that has the number we bought stored in it, as this is the number both hosts and guests will call and send SMS to.

Loading Code Samples...
Language
var twilio = require('twilio');
var VoiceResponse = require('twilio').twiml.VoiceResponse;
var MessagingResponse = require('twilio').twiml.MessagingResponse;
var express = require('express');
var router = express.Router();
var Reservation = require('../models/reservation');

// POST: /commuter/use-sms
router.post('/use-sms', twilio.webhook({ validate: false }), function (req, res) {
  from = req.body.From;
  to   = req.body.To;
  body = req.body.Body;

  gatherOutgoingNumber(from, to)
  .then(function (outgoingPhoneNumber) {
    var messagingResponse = new MessagingResponse();
    messagingResponse.message({ to: outgoingPhoneNumber }, body);

    res.type('text/xml');
    res.send(messagingResponse.toString());
  })
});

// POST: /commuter/use-voice
router.post('/use-voice', twilio.webhook({ validate: false }), function (req, res) {
  from = req.body.From;
  to   = req.body.To;
  body = req.body.Body;

  gatherOutgoingNumber(from, to)
  .then(function (outgoingPhoneNumber) {
    var voiceResponse = new VoiceResponse();
    voiceResponse.play('http://howtodocs.s3.amazonaws.com/howdy-tng.mp3');
    voiceResponse.dial(outgoingPhoneNumber);

    res.type('text/xml');
    res.send(voiceResponse.toString());
  })
});

var gatherOutgoingNumber = function (incomingPhoneNumber, anonymousPhoneNumber) {
  var phoneNumber = anonymousPhoneNumber;

  return Reservation.findOne({ phoneNumber: phoneNumber })
  .deepPopulate('property property.owner guest')
  .then(function (reservation) {
    var hostPhoneNumber = formattedPhoneNumber(reservation.property.owner);
    var guestPhoneNumber = formattedPhoneNumber(reservation.guest);

    // Connect from Guest to Host
    if (guestPhoneNumber === incomingPhoneNumber) {
      outgoingPhoneNumber = hostPhoneNumber;
    }

    // Connect from Host to Guest
    if (hostPhoneNumber === incomingPhoneNumber) {
      outgoingPhoneNumber = guestPhoneNumber;
    }

    return outgoingPhoneNumber;
  })
  .catch(function (err) {
    console.log(err);
  });
}

var formattedPhoneNumber = function(user) {
  return "+" + user.countryCode + user.areaCode + user.phoneNumber;
};

module.exports = router;
routes/commuter.js
Find a Reservation

routes/commuter.js

Next, let's see how to connect the guest and the host via SMS.

Connect Via SMS

Our Twilio application should be configured to send HTTP requests to this controller method on any incoming text message. Our app responds with TwiML to tell Twilio what to do in response to the message.

If the initial message sent to the anonymous number was sent by the host, we forward it on to the guest. Conversely, if the original message was sent by the guest, we forward it to the host.

To find the outgoing number we'll use the gatherOutgoingNumber helper method.

Loading Code Samples...
Language
var twilio = require('twilio');
var VoiceResponse = require('twilio').twiml.VoiceResponse;
var MessagingResponse = require('twilio').twiml.MessagingResponse;
var express = require('express');
var router = express.Router();
var Reservation = require('../models/reservation');

// POST: /commuter/use-sms
router.post('/use-sms', twilio.webhook({ validate: false }), function (req, res) {
  from = req.body.From;
  to   = req.body.To;
  body = req.body.Body;

  gatherOutgoingNumber(from, to)
  .then(function (outgoingPhoneNumber) {
    var messagingResponse = new MessagingResponse();
    messagingResponse.message({ to: outgoingPhoneNumber }, body);

    res.type('text/xml');
    res.send(messagingResponse.toString());
  })
});

// POST: /commuter/use-voice
router.post('/use-voice', twilio.webhook({ validate: false }), function (req, res) {
  from = req.body.From;
  to   = req.body.To;
  body = req.body.Body;

  gatherOutgoingNumber(from, to)
  .then(function (outgoingPhoneNumber) {
    var voiceResponse = new VoiceResponse();
    voiceResponse.play('http://howtodocs.s3.amazonaws.com/howdy-tng.mp3');
    voiceResponse.dial(outgoingPhoneNumber);

    res.type('text/xml');
    res.send(voiceResponse.toString());
  })
});

var gatherOutgoingNumber = function (incomingPhoneNumber, anonymousPhoneNumber) {
  var phoneNumber = anonymousPhoneNumber;

  return Reservation.findOne({ phoneNumber: phoneNumber })
  .deepPopulate('property property.owner guest')
  .then(function (reservation) {
    var hostPhoneNumber = formattedPhoneNumber(reservation.property.owner);
    var guestPhoneNumber = formattedPhoneNumber(reservation.guest);

    // Connect from Guest to Host
    if (guestPhoneNumber === incomingPhoneNumber) {
      outgoingPhoneNumber = hostPhoneNumber;
    }

    // Connect from Host to Guest
    if (hostPhoneNumber === incomingPhoneNumber) {
      outgoingPhoneNumber = guestPhoneNumber;
    }

    return outgoingPhoneNumber;
  })
  .catch(function (err) {
    console.log(err);
  });
}

var formattedPhoneNumber = function(user) {
  return "+" + user.countryCode + user.areaCode + user.phoneNumber;
};

module.exports = router;
routes/commuter.js
Connect Via SMS

routes/commuter.js

Let's see how to connect the guest and the host via phone call next.

Connect Via Phone Call

Our Twilio application will send HTTP requests to this method on any incoming voice call. Our app responds with TwiML instructions that tell Twilio to Play an introductory MP3 audio file and then Dial either the guest or host, depending on who initiated the call.

Loading Code Samples...
Language
var twilio = require('twilio');
var VoiceResponse = require('twilio').twiml.VoiceResponse;
var MessagingResponse = require('twilio').twiml.MessagingResponse;
var express = require('express');
var router = express.Router();
var Reservation = require('../models/reservation');

// POST: /commuter/use-sms
router.post('/use-sms', twilio.webhook({ validate: false }), function (req, res) {
  from = req.body.From;
  to   = req.body.To;
  body = req.body.Body;

  gatherOutgoingNumber(from, to)
  .then(function (outgoingPhoneNumber) {
    var messagingResponse = new MessagingResponse();
    messagingResponse.message({ to: outgoingPhoneNumber }, body);

    res.type('text/xml');
    res.send(messagingResponse.toString());
  })
});

// POST: /commuter/use-voice
router.post('/use-voice', twilio.webhook({ validate: false }), function (req, res) {
  from = req.body.From;
  to   = req.body.To;
  body = req.body.Body;

  gatherOutgoingNumber(from, to)
  .then(function (outgoingPhoneNumber) {
    var voiceResponse = new VoiceResponse();
    voiceResponse.play('http://howtodocs.s3.amazonaws.com/howdy-tng.mp3');
    voiceResponse.dial(outgoingPhoneNumber);

    res.type('text/xml');
    res.send(voiceResponse.toString());
  })
});

var gatherOutgoingNumber = function (incomingPhoneNumber, anonymousPhoneNumber) {
  var phoneNumber = anonymousPhoneNumber;

  return Reservation.findOne({ phoneNumber: phoneNumber })
  .deepPopulate('property property.owner guest')
  .then(function (reservation) {
    var hostPhoneNumber = formattedPhoneNumber(reservation.property.owner);
    var guestPhoneNumber = formattedPhoneNumber(reservation.guest);

    // Connect from Guest to Host
    if (guestPhoneNumber === incomingPhoneNumber) {
      outgoingPhoneNumber = hostPhoneNumber;
    }

    // Connect from Host to Guest
    if (hostPhoneNumber === incomingPhoneNumber) {
      outgoingPhoneNumber = guestPhoneNumber;
    }

    return outgoingPhoneNumber;
  })
  .catch(function (err) {
    console.log(err);
  });
}

var formattedPhoneNumber = function(user) {
  return "+" + user.countryCode + user.areaCode + user.phoneNumber;
};

module.exports = router;
routes/commuter.js
Connect Via Phone Call

routes/commuter.js

That's it! We've just implemented anonymous communications that allow your customers to connect while protecting their privacy.

Where to Next?

If you're a Node.js developer working with Twilio, you might want to check out these other tutorials:

IVR: Phone Tree

Easily route callers to the right people and information with an IVR (interactive voice response) system.

Automated Survey

Instantly collect structured data from your users with a survey conducted over a voice call or SMS text messages. Learn how to create your own survey in the language and framework of your choice.

Did this help?

Thanks for checking out this tutorial! If you have any feedback to share with us, we'd love to hear it. Tweet @twilio to let us know what you think.

Andrew Baker
David Prothero
Jose Oliveros
Samuel Mendes

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.

1 / 1
Loading Code Samples...
var twilio = require('twilio');
var MessagingResponse = require('twilio').twiml.MessagingResponse;
var express = require('express');
var router = express.Router();
var Property = require('../models/property');
var Reservation = require('../models/reservation');
var User = require('../models/user');
var notifier = require('../lib/notifier');
var purchaser = require('../lib/purchaser');
var middleware = require('../lib/middleware');

router.get('/', middleware.isAuthenticated, function (req, res) {
  var userId = req.user.id;
  Reservation.find({})
  .deepPopulate('property property.owner guest')
  .then(function (reservations) {
    var hostReservations = reservations.filter(function (reservation) {
      return reservation.property.owner.id === userId;
    });

    res.render('reservations/index', { reservations: hostReservations, user: req.user });
  });
});

// POST: /reservations
router.post('/', function (req, res) {
  var propertyId = req.body.propertyId;
  var user = req.user;

  Property.findOne({ _id: propertyId })
  .then(function (property) {
    var reservation = new Reservation({
      message: req.body.message,
      property: propertyId,
      guest: user.id
    });

    return reservation.save();
  })
  .then(function () {
    notifier.sendNotification();
    res.redirect('/properties');
  })
  .catch(function(err) {
    console.log(err);
  });
});

// POST: /reservations/handle
router.post('/handle', twilio.webhook({validate: false}), function (req, res) {
  var from = req.body.From;
  var smsRequest = req.body.Body;

  var smsResponse;

  User.findOne({phoneNumber: from})
    .then(function (host) {
      return Reservation.findOne({status: 'pending'})
        .deepPopulate('property property.owner guest')
    })
    .then(function (reservation) {
      if (reservation === null) {
        throw 'No pending reservations';
      }

      var hostAreaCode = reservation.property.owner.areaCode;

      var phoneNumber = purchaser.purchase(hostAreaCode);
      var reservationPromise = Promise.resolve(reservation);

      return Promise.all([phoneNumber, reservationPromise]);
    })
    .then(function (data) {
      var phoneNumber = data[0];
      var reservation = data[1];

      if (isSmsRequestAccepted(smsRequest)) {
        reservation.status = "confirmed";
        reservation.phoneNumber = phoneNumber;
      } else {
        reservation.status = "rejected";
      }
      return reservation.save();
    })
    .then(function (reservation) {
      var message = "You have successfully " + reservation.status + " the reservation";
      respond(res, message);
    })
    .catch(function (err) {
      console.log(err);
      var message = "Sorry, it looks like you do not have any reservations to respond to";
      respond(res, message);
    });
});

var isSmsRequestAccepted = function (smsRequest) {
  return smsRequest.toLowerCase() === 'accept';
};

var respond = function(res, message) {
  var messagingResponse = new MessagingResponse();
  messagingResponse.message(message);

  res.type('text/xml');
  res.send(messagingResponse.toString());
}

module.exports = router;
var twilio = require('twilio');
var MessagingResponse = require('twilio').twiml.MessagingResponse;
var express = require('express');
var router = express.Router();
var Property = require('../models/property');
var Reservation = require('../models/reservation');
var User = require('../models/user');
var notifier = require('../lib/notifier');
var purchaser = require('../lib/purchaser');
var middleware = require('../lib/middleware');

router.get('/', middleware.isAuthenticated, function (req, res) {
  var userId = req.user.id;
  Reservation.find({})
  .deepPopulate('property property.owner guest')
  .then(function (reservations) {
    var hostReservations = reservations.filter(function (reservation) {
      return reservation.property.owner.id === userId;
    });

    res.render('reservations/index', { reservations: hostReservations, user: req.user });
  });
});

// POST: /reservations
router.post('/', function (req, res) {
  var propertyId = req.body.propertyId;
  var user = req.user;

  Property.findOne({ _id: propertyId })
  .then(function (property) {
    var reservation = new Reservation({
      message: req.body.message,
      property: propertyId,
      guest: user.id
    });

    return reservation.save();
  })
  .then(function () {
    notifier.sendNotification();
    res.redirect('/properties');
  })
  .catch(function(err) {
    console.log(err);
  });
});

// POST: /reservations/handle
router.post('/handle', twilio.webhook({validate: false}), function (req, res) {
  var from = req.body.From;
  var smsRequest = req.body.Body;

  var smsResponse;

  User.findOne({phoneNumber: from})
    .then(function (host) {
      return Reservation.findOne({status: 'pending'})
        .deepPopulate('property property.owner guest')
    })
    .then(function (reservation) {
      if (reservation === null) {
        throw 'No pending reservations';
      }

      var hostAreaCode = reservation.property.owner.areaCode;

      var phoneNumber = purchaser.purchase(hostAreaCode);
      var reservationPromise = Promise.resolve(reservation);

      return Promise.all([phoneNumber, reservationPromise]);
    })
    .then(function (data) {
      var phoneNumber = data[0];
      var reservation = data[1];

      if (isSmsRequestAccepted(smsRequest)) {
        reservation.status = "confirmed";
        reservation.phoneNumber = phoneNumber;
      } else {
        reservation.status = "rejected";
      }
      return reservation.save();
    })
    .then(function (reservation) {
      var message = "You have successfully " + reservation.status + " the reservation";
      respond(res, message);
    })
    .catch(function (err) {
      console.log(err);
      var message = "Sorry, it looks like you do not have any reservations to respond to";
      respond(res, message);
    });
});

var isSmsRequestAccepted = function (smsRequest) {
  return smsRequest.toLowerCase() === 'accept';
};

var respond = function(res, message) {
  var messagingResponse = new MessagingResponse();
  messagingResponse.message(message);

  res.type('text/xml');
  res.send(messagingResponse.toString());
}

module.exports = router;
var config = require('../config');
var client = require('twilio')(config.accountSid, config.authToken);

var purchase = function (areaCode) {
  var phoneNumber;

  return client.availablePhoneNumbers('US').local.list({
        areaCode: areaCode,
        voiceEnabled: true,
        smsEnabled: true
  }).then(function(searchResults) {
    if (searchResults.availablePhoneNumbers.length === 0) {
      throw { message: 'No numbers found with that area code' };
    }

    return client.incomingPhoneNumbers.create({
      phoneNumber: searchResults.availablePhoneNumbers[0].phoneNumber,
      voiceApplicationSid: config.applicationSid,
      smsApplicationSid: config.applicationSid
    });
  }).then(function(number) {
    return number.phone_number;
  });
}

exports.purchase = purchase;
var twilio = require('twilio');
var VoiceResponse = require('twilio').twiml.VoiceResponse;
var MessagingResponse = require('twilio').twiml.MessagingResponse;
var express = require('express');
var router = express.Router();
var Reservation = require('../models/reservation');

// POST: /commuter/use-sms
router.post('/use-sms', twilio.webhook({ validate: false }), function (req, res) {
  from = req.body.From;
  to   = req.body.To;
  body = req.body.Body;

  gatherOutgoingNumber(from, to)
  .then(function (outgoingPhoneNumber) {
    var messagingResponse = new MessagingResponse();
    messagingResponse.message({ to: outgoingPhoneNumber }, body);

    res.type('text/xml');
    res.send(messagingResponse.toString());
  })
});

// POST: /commuter/use-voice
router.post('/use-voice', twilio.webhook({ validate: false }), function (req, res) {
  from = req.body.From;
  to   = req.body.To;
  body = req.body.Body;

  gatherOutgoingNumber(from, to)
  .then(function (outgoingPhoneNumber) {
    var voiceResponse = new VoiceResponse();
    voiceResponse.play('http://howtodocs.s3.amazonaws.com/howdy-tng.mp3');
    voiceResponse.dial(outgoingPhoneNumber);

    res.type('text/xml');
    res.send(voiceResponse.toString());
  })
});

var gatherOutgoingNumber = function (incomingPhoneNumber, anonymousPhoneNumber) {
  var phoneNumber = anonymousPhoneNumber;

  return Reservation.findOne({ phoneNumber: phoneNumber })
  .deepPopulate('property property.owner guest')
  .then(function (reservation) {
    var hostPhoneNumber = formattedPhoneNumber(reservation.property.owner);
    var guestPhoneNumber = formattedPhoneNumber(reservation.guest);

    // Connect from Guest to Host
    if (guestPhoneNumber === incomingPhoneNumber) {
      outgoingPhoneNumber = hostPhoneNumber;
    }

    // Connect from Host to Guest
    if (hostPhoneNumber === incomingPhoneNumber) {
      outgoingPhoneNumber = guestPhoneNumber;
    }

    return outgoingPhoneNumber;
  })
  .catch(function (err) {
    console.log(err);
  });
}

var formattedPhoneNumber = function(user) {
  return "+" + user.countryCode + user.areaCode + user.phoneNumber;
};

module.exports = router;
var twilio = require('twilio');
var VoiceResponse = require('twilio').twiml.VoiceResponse;
var MessagingResponse = require('twilio').twiml.MessagingResponse;
var express = require('express');
var router = express.Router();
var Reservation = require('../models/reservation');

// POST: /commuter/use-sms
router.post('/use-sms', twilio.webhook({ validate: false }), function (req, res) {
  from = req.body.From;
  to   = req.body.To;
  body = req.body.Body;

  gatherOutgoingNumber(from, to)
  .then(function (outgoingPhoneNumber) {
    var messagingResponse = new MessagingResponse();
    messagingResponse.message({ to: outgoingPhoneNumber }, body);

    res.type('text/xml');
    res.send(messagingResponse.toString());
  })
});

// POST: /commuter/use-voice
router.post('/use-voice', twilio.webhook({ validate: false }), function (req, res) {
  from = req.body.From;
  to   = req.body.To;
  body = req.body.Body;

  gatherOutgoingNumber(from, to)
  .then(function (outgoingPhoneNumber) {
    var voiceResponse = new VoiceResponse();
    voiceResponse.play('http://howtodocs.s3.amazonaws.com/howdy-tng.mp3');
    voiceResponse.dial(outgoingPhoneNumber);

    res.type('text/xml');
    res.send(voiceResponse.toString());
  })
});

var gatherOutgoingNumber = function (incomingPhoneNumber, anonymousPhoneNumber) {
  var phoneNumber = anonymousPhoneNumber;

  return Reservation.findOne({ phoneNumber: phoneNumber })
  .deepPopulate('property property.owner guest')
  .then(function (reservation) {
    var hostPhoneNumber = formattedPhoneNumber(reservation.property.owner);
    var guestPhoneNumber = formattedPhoneNumber(reservation.guest);

    // Connect from Guest to Host
    if (guestPhoneNumber === incomingPhoneNumber) {
      outgoingPhoneNumber = hostPhoneNumber;
    }

    // Connect from Host to Guest
    if (hostPhoneNumber === incomingPhoneNumber) {
      outgoingPhoneNumber = guestPhoneNumber;
    }

    return outgoingPhoneNumber;
  })
  .catch(function (err) {
    console.log(err);
  });
}

var formattedPhoneNumber = function(user) {
  return "+" + user.countryCode + user.areaCode + user.phoneNumber;
};

module.exports = router;
var twilio = require('twilio');
var VoiceResponse = require('twilio').twiml.VoiceResponse;
var MessagingResponse = require('twilio').twiml.MessagingResponse;
var express = require('express');
var router = express.Router();
var Reservation = require('../models/reservation');

// POST: /commuter/use-sms
router.post('/use-sms', twilio.webhook({ validate: false }), function (req, res) {
  from = req.body.From;
  to   = req.body.To;
  body = req.body.Body;

  gatherOutgoingNumber(from, to)
  .then(function (outgoingPhoneNumber) {
    var messagingResponse = new MessagingResponse();
    messagingResponse.message({ to: outgoingPhoneNumber }, body);

    res.type('text/xml');
    res.send(messagingResponse.toString());
  })
});

// POST: /commuter/use-voice
router.post('/use-voice', twilio.webhook({ validate: false }), function (req, res) {
  from = req.body.From;
  to   = req.body.To;
  body = req.body.Body;

  gatherOutgoingNumber(from, to)
  .then(function (outgoingPhoneNumber) {
    var voiceResponse = new VoiceResponse();
    voiceResponse.play('http://howtodocs.s3.amazonaws.com/howdy-tng.mp3');
    voiceResponse.dial(outgoingPhoneNumber);

    res.type('text/xml');
    res.send(voiceResponse.toString());
  })
});

var gatherOutgoingNumber = function (incomingPhoneNumber, anonymousPhoneNumber) {
  var phoneNumber = anonymousPhoneNumber;

  return Reservation.findOne({ phoneNumber: phoneNumber })
  .deepPopulate('property property.owner guest')
  .then(function (reservation) {
    var hostPhoneNumber = formattedPhoneNumber(reservation.property.owner);
    var guestPhoneNumber = formattedPhoneNumber(reservation.guest);

    // Connect from Guest to Host
    if (guestPhoneNumber === incomingPhoneNumber) {
      outgoingPhoneNumber = hostPhoneNumber;
    }

    // Connect from Host to Guest
    if (hostPhoneNumber === incomingPhoneNumber) {
      outgoingPhoneNumber = guestPhoneNumber;
    }

    return outgoingPhoneNumber;
  })
  .catch(function (err) {
    console.log(err);
  });
}

var formattedPhoneNumber = function(user) {
  return "+" + user.countryCode + user.areaCode + user.phoneNumber;
};

module.exports = router;