npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

plivode

v0.2.3

Published

A lightweight scalable Plivo application framework.

Readme

#Plivode

Plivode is a lightweight scalable application framework for creating Plivo apps with NodeJS.

Installing

npm install plivode

Getting Started

Let's run through a few examples to see how Plivode works.

Example: Hello, World!

var plivode = require('plivode');

new plivode.App({
   appID: '[your Plivo app ID]',
   authID: '[your Plivo auth ID]',
   authToken: '[your Plivo auth token]',
   rootUrl: '[the root URL this app is accessible by Plivo]'
})
.on('answer', function(params, response) {
   response
       .speak('Hello, world!')
       .send();
});

It doesn't get much simpler than this! Here we create a new Plivode app, which will answer any received phone calls with "Hello, world!"

Plivode makes use of Express to run a web server for receiving messages from Plivo.

Simply specify the URL of your server, and make sure the port you specify is accesible to the outside world. For example, if your Plivode app is running on port 1919 of plivode-app.example.com, you'd pass: rootUrl: 'http://plivode-app.example.com:1919'

Application Events

Your Plivode app will raise events when you need to respond to a phone call or sms message. The standard Plivo events are:

  • answer - raised when a call is received by any of the phone numbers associated with your app.
  • message - raised when a sms message is received by any of the phone numbers associated with your app.
  • hangup - raised when a call is ended.

Example: Parrot

See it in action! Send a sms to (949) 484-8425. Within a few seconds you'll get a call speaking your message.

var plivode = require('plivode');

new plivode.App({
    appID: '[your Plivo app ID]',
    authID: '[your Plivo auth ID]',
    authToken: '[your Plivo auth token]',
    rootUrl: '[the root URL this app is accessible by Plivo]'
})
.on('message', function(params, response) {
    // When a sms is received, make an outbound call to the number that sent the sms,
    // passing the text of the sms to the "parrot" action.
    this.Call.outbound('[your Plivo phone number]', params.From, ['parrot', params.Text]);

    // Send a blank response back, so Plivo knows we processed the message and not to resend it.
    response.send();
})
.on('parrot/:message', function(params, response) {
    // The user answered the return call, so speak the text of the sms that they sent, and repeat it 3 times.
    response
        .speak(params.message, { loop: 3 })
        .send();
});

Here we listen for sms messages, and when one is received we call the number back and speak the message 3 times.

Plivode provides support for the entire Plivo REST API. Here we use Call.outbound to make the call.

Notice that we specify the custom event parrot/:message. This event is raised when the outbound call is answered. Since event names map directly to Express routes, we're able to use Express' powerful routing engine to specify parameters within the event name.

When we make the outbound call, we pass in the action route ['parrot', params.Text]. The first field of your route must be the event name, and the remaining fields can be parameters to pass to the next step of the call. If you don't need to pass along parameters you can simply pass the event name as a string.

Example: Guess the Number

See it in action! Call (949) 484-8425.

Pick a number between 1 and 100, and the app will try to guess it. If you're thinking of a lower number press *; higher press #; and if the guess is correct press 0.

var plivode = require('plivode');

new plivode.App({
    appID: '[your Plivo app ID]',
    authID: '[your Plivo auth ID]',
    authToken: '[your Plivo auth token]',
    rootUrl: '[the root URL this app is accessible by Plivo]'
})
.on('answer', function(params, response) {
    console.log('answered call from: ' + params.From);

    var MIN_GUESS = 1,
        MAX_GUESS = 100,
        guess = MIN_GUESS + Math.round(Math.random() * (MAX_GUESS - MIN_GUESS));

    response.speak('Pick a number between one and one hundred')     // Spelling out 100, otherwise speak pronounces it "1-o-o".
        .wait(3)
        .speak("I'm guessing it's " + guess)
        .getDigits({
            action: ['guess', MIN_GUESS, MAX_GUESS, guess],
            numDigits: 1,
            validDigits: '*#0',
            finishOnKey: '123456789',
            timeout: 45
        }, function() {
            response.speak("If the number you're thinking of is lower than " + guess + ", press star; " +
                "if it's higher press pound; and if it's correct press 0.")
        })
        .speak("I didn't catch that. Goodbye.")
        .send();
})
.on('guess/:min/:max/:guess', function(params, response) {
    var min = parseInt(params.min, 10),
        max = parseInt(params.max, 10),
        guess = parseInt(params.guess, 10),
        newGuess,
        direction;

    // Look at what digit the user pressed to determine how to guess next, or if we guessed right.
    switch (params.Digits) {
        case '*':
            direction = 'lower';
            max = guess - 1;
            break;
        case '#':
            direction = 'higher';
            min = guess + 1;
            break;
        case '0':
            console.log(params.From + ': ' + guess + ' was correct!');
            response
                .speak('Hooray! Thanks for playing. Goodbye.')
                .send();
            return;
    }

    if (min > max) {
        // The user told us the number is higher than the min, and less than the max, no compute.
        response
            .speak("I've run out of numbers. Goodbye.")
            .send();
        return;
    } else if (max === min) {
        // We've narrowed it down to one number
        newGuess = min;
    } else {
        // We could just do a binary search and guess right in the middle, but
        // let's add a bit of randomness to make things a bit less predictable.
        var randomnessAmount = Math.round((max - min) * 0.2),
        random = Math.random() * randomnessAmount - randomnessAmount / 2;

        newGuess = Math.round((max + min - randomnessAmount) / 2 + random);
    }

    // Pick a random start to the question to add some variability.
    var questions = ['How about ', 'Is it ', 'Perhaps ', 'Could it be '],
        question = questions[Math.floor(Math.random() * questions.length)] + newGuess + '?';

    console.log([params.From,  ': The number is ', direction,  ' than ' + guess, '. ', question].join(''));

    // Ask the user again.
    response
        .getDigits({
            action: ['guess', min, max, newGuess],
            numDigits: 1,
            validDigits: '*#0',
            finishOnKey: '123456789',
            timeout: 45
        }, function() {
            response.speak(question)
        })
        .speak("I didn't catch that. Goodbye.")
        .send();
})
.on('hangup', function(params) {
    console.log('call ended with: ' + params.From);
    console.log(params);
});

Documentation

More documentation is on the way! For now, partial documentation is available here.