README.md

ExTwiml 
===================
[![Build Status](https://travis-ci.org/danielberkompas/ex_twiml.svg)](https://travis-ci.org/danielberkompas/ex_twiml)
[![Hex Version](http://img.shields.io/hexpm/v/ex_twiml.svg)](https://hex.pm/packages/ex_twiml)
[![Inline docs](http://inch-ci.org/github/danielberkompas/ex_twiml.svg?branch=master)](http://inch-ci.org/github/danielberkompas/extwiml)

Generate TwiML for your [Twilio](http://twilio.com) integration, right inside
Elixir! This is the first step toward a comprehensive Twilio integration library
I'm writing for Elixir, but it can be used entirely on its own.

## Installation

ExTwiml can be installed through mix as a hex package. First, update your 
dependencies in `mix.exs`.

```elixir
defp deps
  [{:ex_twiml, "~> 1.1.1"}]
end
```

If you prefer, you can depend on the latest version from Github:

```elixir
defp deps
  [{:ex_twiml, github: "danielberkompas/ex_twiml"}]
end
```

Then run `mix deps.get`, and ExTwiml will be installed.

## Usage

Import the `ExTwiml` module into your module, and then use the `twiml` macro to 
generate your TwiML, like so:

```elixir
defmodule YourModule do
  import ExTwiml

  def render do
    twiml do
      play "/assets/welcome.mp3"
      gather digits: 4, finish_on_key: "#" do
        say """
        Please enter the last four digits of your credit card number, followed 
        by the pound sign.
        """, voice: "woman"
      end
    end
  end
end
```

You can then render the TwiML by calling `YourModule.render/0`. The output will 
be a binary in this format:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Play>/assets/welcome.mp3</Play>
  <Gather digits="4" finishOnKey="#">
    <Say voice="woman">
      Please enter the last four digits of your credit card number, followed by
      the pound sign.
    </Say>
  </Gather>
</Response>
```

The `twiml` macro simply returns a binary (or string), so you're not limited to
the pattern above. Just use `twiml` wherever you need a TwiML string.

### Options

If you are integrating `ExTwilio` into a state machine for handling your call
flows, you might find the `option` macro useful. It helps you dry up your code
by recording a user's option at the same time as you `Say` it to the user.

```elixir
extensions = ... # load from database

{opts, _xml} = twiml do
  Enum.each extensions, fn ext ->
    option ext.code, "Press #{ext.number} for #{ext.name}", [menu: :call_person], [voice: "woman"]
  end
end

opts # => [{301, [menu: :call_person]}, ...]
```

The `option` macro is really just an enhanced `say` macro under the hood, so the
twiml generated by the above will look like this:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Say voice="woman">
    Press 301 for Engineering Department
  </Say>
</Response>
```

## Supported Verbs and Nouns
See the [Twilio Documentation](https://www.twilio.com/docs/api/twiml) for a
complete list of verbs supported by Twilio. ExTwiml has built in macros for the
following verbs and nouns:

- [Say](https://www.twilio.com/docs/api/2010-04-01/twiml/say)
- [Play](https://www.twilio.com/docs/api/2010-04-01/twiml/play)
- [Gather](https://www.twilio.com/docs/api/2010-04-01/twiml/gather)
- [Record](https://www.twilio.com/docs/api/2010-04-01/twiml/record)
- [Sms](https://www.twilio.com/docs/api/2010-04-01/twiml/sms)
- [Dial](https://www.twilio.com/docs/api/2010-04-01/twiml/dial)
    - [Number](https://www.twilio.com/docs/api/2010-04-01/twiml/number)
    - [Sip](https://www.twilio.com/docs/api/2010-04-01/twiml/sip)
    - [Client](https://www.twilio.com/docs/api/2010-04-01/twiml/client)
    - [Conference](https://www.twilio.com/docs/api/2010-04-01/twiml/conference)
    - [Queue](https://www.twilio.com/docs/api/2010-04-01/twiml/queue)
- [Enqueue](https://www.twilio.com/docs/api/2010-04-01/twiml/enqueue)
- [Leave](https://www.twilio.com/docs/api/2010-04-01/twiml/leave)
- [Hangup](https://www.twilio.com/docs/api/2010-04-01/twiml/hangup)
- [Redirect](https://www.twilio.com/docs/api/2010-04-01/twiml/redirect)
- [Reject](https://www.twilio.com/docs/api/2010-04-01/twiml/reject)
- [Pause](https://www.twilio.com/docs/api/2010-04-01/twiml/pause)
- [Message](https://www.twilio.com/docs/api/2010-04-01/twiml/message)
    - [Body](https://www.twilio.com/docs/api/2010-04-01/twiml/body)
    - [Media](https://www.twilio.com/docs/api/2010-04-01/twiml/media)
- [Redirect](https://www.twilio.com/docs/api/2010-04-01/twiml/redirect)

Supported verbs can be called in three forms:

```elixir
# Verbs that support nesting, like <Gather> and <Dial>:
verb option_1: "value", option_2: "value" do
    # Nested verbs here
end
# => "<Verb option1="value" option2="value">Nested verbs here</Verb>":

# Verbs that don't support nesting, like <Say>
twiml do
  verb "Inner text", option_1: "value", option_2: "value"
end
# => "<Verb option1="value" option2="value">Inner text</Verb>"

# Verbs that have no inner content, like <Reject>:
reject reason: "busy"
# => "<Reject reason="busy" />"
```

To maximize compatibility with future versions of the TwiML spec, ExTwiml
**does not** validate the attributes passed to the various verbs to ensure that
they are supported by Twilio. You'll need to do this yourself.

### Unsupported Verbs?
If the Twilio API adds a verb and I haven't yet created a macro for it, you can do
two things:

1. Submit a PR to add it
2. Use the `tag` macro in the meantime while the PR is reviewed

The tag macro can be used to create arbitrary XML tags in the output, like this:

```elixir
tag :custom, option_1: "value" do
  tag :speak, do: "Whatever you say, boss!"
end
# => "<Custom option1="value"><Speak>Whatever you say, boss!</Speak></Custom>"
```

## Contributing

Contributions are welcome!

1. Fork the repository
2. Code up your changes
3. Submit a PR back here with your fix.