Code Monkey home page Code Monkey logo

twiml's Introduction

TwiML

Go Doc CircleCI

A library for producing TwiML XML markup for use with the Twilio API. This library can generate TwiML responses and provides helpers for processing callbacks and requests from Twilio.

This library does not yet cover the entire TwiML API, but pull requests are welcome if you find something missing.

Processing a request from Twilio

The library contains helpers to bind incoming Twilio requests to a struct that includes all of the available info from the request. Most initial requests from Twilio are of type twiml.VoiceRequest. Other request types are possible as a result of callbacks you register in your response. See the GoDoc for details.

func(w http.ResponseWriter, r *http.Request) {
    var vr twiml.VoiceRequest
    if err := twiml.Bind(&vr, r); err != nil {
        http.Error(w, http.StatusText(400), 400)
        return
    }
    fmt.Printf("Incoming call from %s", vr.From)
}

Constructing a response using TwiML

Once you receive a request from the Twilio API, you construct a TwiML response to provide directions for how to deal with the call. This library includes (most of) the allowable verbs and rules to validate that your response is constructed properly.

// CallRequest will return XML to connect to the forwarding number
func CallRequest(cfg Config) func(http.ResponseWriter, *http.Request) {
    return func(w http.ResponseWriter, r *http.Request) {

        // Bind the request
        var cr twiml.VoiceRequest
        if err := twiml.Bind(&cr, r); err != nil {
            http.Error(w, http.StatusText(400), 400)
            return
        }

        // Create a new response container
        res := twiml.NewResponse()

        switch status := cr.CallStatus; status {

        // Call is already in progress, tell Twilio to continue
        case twiml.InProgress:
            w.WriteHeader(200)
            return

        // Call is ringing but has not been connected yet, respond with
        // a forwarding number
        case twiml.Ringing, twiml.Queued:
            // Create a new Dial verb
            d := twiml.Dial{
                Number:   cfg.ForwardingNumber,
                Action:   "action/",
                Timeout:  15,
                CallerID: cr.To,
            }

            // Add the verb to the response
            res.Add(&d)
            
            // Validate and encode the response.  Validation is done
            // automatically before the response is encoded.
            b, err := res.Encode()
            if err != nil {
                http.Error(w, http.StatusText(502), 502)
                return
            }

            // Write the XML response to the http.ReponseWriter
            if _, err := w.Write(b); err != nil {
                http.Error(w, http.StatusText(502), 502)
                return
            }
            w.Header().Set("Content-Type", "application/xml")
            w.WriteHeader(200)
            return

        // Call is over, hang up
        default:
            res.Add(&twiml.Hangup{})
            b, err := res.Encode()
            if err != nil {
                http.Error(w, http.StatusText(502), 502)
                return
            }
            if _, err := w.Write(b); err != nil {
                http.Error(w, http.StatusText(502), 502)
                return
            }
            w.Header().Set("Content-Type", "application/xml")
            w.WriteHeader(200)
            return
        }
    }
}

The example above shows the general flow of constructing a response. Start with creating a new response container, then use the Add() method to add a TwiML verb with its appropriate configuration. Verbs that allow other verbs to be nested within them expose their own Add() method. On the call to Encode() the complete response is validated to ensure that the response is properly configured.

More examples

For a more detailed example of constructing a small TwiML response server, see my Twilio Voice project which is a Google-voice clone that forwards calls to your number and handles transcribing voicemails.

twiml's People

Contributors

andrewpage avatar btburke avatar ivy avatar krislange avatar raidancampbell avatar tomaspinho avatar toorop avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

twiml's Issues

[Bug] Dial.Number is a required field

I'm trying to generate the following TwiML:

<Response>
    <Dial>
        <Queue>my-queue-name</Queue>
    </Dial>
</Response>

Here is the Go code I am using:

// Connect rep to personal queue
res := twiml.NewResponse()
dial := twiml.Dial{}
dial.Add(&twiml.Queue{
  Name: "my-queue-name",
})
res.Add(&dial)

// handle error on XML generate
body, err := res.Encode()
if err != nil {
    panic(err)
}

Encode() returns an error which, when paniced, outputs the following:

panic <nil> Invalid TwiML markup:
Invalid TwiML markup:
Dial did not pass validation <nil>

I've identified the bug in the code. Dial.Number field is explicitly required by validations (https://github.com/BTBurke/twiml/blob/master/vocabulary.go#L110), but it seems like you have carved out a case for the SIP verb block. The SIP verb is not the only <Dial> child that does not require a number. To my knowledge, <Client>, <Conference>, and <Queue> do not require a number.

I think an appropriate fix would be to make the hasSIPChild flag more general, to include all <Dial> children that don't require a number. I plan to implement this fix myself, but I wanted to document this bug in case I don't get around to it.

Create a new release

I am use Dep to manage my Go packages. By default it uses for the most recent Git tag as the version it pulls down.

I was receiving an error related to Dial validation when using the Sip noun. It took me a second to realize that a fix for Dial validation in this circumstance was added ~10 days ago. And Dep was not pulling down the latest commit on master but instead the v1.0.0 tag. To fix this I made Dep track the master branch of this repository.

It would be helpful if a new tag was created with the Dial validation fix.

If you are planning on not using tags in the future but instead having people track the master branch this is fine, feel free to close this issue.

PS: Thank you so much for maintaining this library. It has made using Twilio with Go super easy!

[Bug] Play.URL is a required field

I'm trying to use this library to generate the following XML.

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Play digits="9w9w9"></Play>
</Response>

I generate this XML using the following snippet

res := twiml.NewResponse()
res.Add(&twiml.Play{Digits: "9w9w9"})

b, _ := res.Encode()

The twiml library requires URL to be set; however, Twilio does not require the URL field be set for Play.

I have confirmed by sending the following in response to a Twilio request, and it succeeded.

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Play></Play>
</Response>

I believe the URL field should be removed from Play's validation to support the above XML generation. Creating this issue to provide context for an incoming PR.

License?

Please set the License for this repo. Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.