Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,6 @@ omit =
homeassistant/components/tradfri.py
homeassistant/components/*/tradfri.py

homeassistant/components/twilio.py
homeassistant/components/notify/twilio_sms.py
homeassistant/components/notify/twilio_call.py

Expand Down
58 changes: 0 additions & 58 deletions homeassistant/components/twilio.py

This file was deleted.

18 changes: 18 additions & 0 deletions homeassistant/components/twilio/.translations/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"config": {
"title": "Twilio",
"step": {
"user": {
"title": "Set up the Twilio Webhook",
"description": "Are you sure you want to set up Twilio?"
}
},
"abort": {
"one_instance_allowed": "Only a single instance is necessary.",
"not_internet_accessible": "Your Home Assistant instance needs to be accessible from the internet to receive Twilio messages."
},
"create_entry": {
"default": "To send events to Home Assistant, you will need to setup [Webhooks with Twilio]({twilio_url}).\n\nFill in the following info:\n\n- URL: `{webhook_url}`\n- Method: POST\n- Content Type: application/x-www-form-urlencoded\n\nSee [the documentation]({docs_url}) on how to configure automations to handle incoming data."
}
}
}
76 changes: 76 additions & 0 deletions homeassistant/components/twilio/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""
Support for Twilio.

For more details about this component, please refer to the documentation at
https://home-assistant.io/components/twilio/
"""
import voluptuous as vol

import homeassistant.helpers.config_validation as cv
from homeassistant.const import CONF_WEBHOOK_ID
from homeassistant.helpers import config_entry_flow

REQUIREMENTS = ['twilio==6.19.1']
DEPENDENCIES = ['webhook']

DOMAIN = 'twilio'

CONF_ACCOUNT_SID = 'account_sid'
CONF_AUTH_TOKEN = 'auth_token'

DATA_TWILIO = DOMAIN

RECEIVED_DATA = '{}_data_received'.format(DOMAIN)

CONFIG_SCHEMA = vol.Schema({
vol.Optional(DOMAIN): vol.Schema({
vol.Required(CONF_ACCOUNT_SID): cv.string,
vol.Required(CONF_AUTH_TOKEN): cv.string,
}),
}, extra=vol.ALLOW_EXTRA)


async def async_setup(hass, config):
"""Set up the Twilio component."""
from twilio.rest import TwilioRestClient
if DOMAIN not in config:
return True

conf = config[DOMAIN]
hass.data[DATA_TWILIO] = TwilioRestClient(
conf.get(CONF_ACCOUNT_SID), conf.get(CONF_AUTH_TOKEN))
return True


async def handle_webhook(hass, webhook_id, request):
"""Handle incoming webhook from Twilio for inbound messages and calls."""
from twilio.twiml import TwiML

data = dict(await request.post())
data['webhook_id'] = webhook_id
hass.bus.async_fire(RECEIVED_DATA, dict(data))

return TwiML().to_xml()


async def async_setup_entry(hass, entry):
"""Configure based on config entry."""
hass.components.webhook.async_register(
entry.data[CONF_WEBHOOK_ID], handle_webhook)
return True


async def async_unload_entry(hass, entry):
"""Unload a config entry."""
hass.components.webhook.async_unregister(entry.data[CONF_WEBHOOK_ID])
return True

config_entry_flow.register_webhook_flow(
DOMAIN,
'Twilio Webhook',
{
'twilio_url':
'https://www.twilio.com/docs/glossary/what-is-a-webhook',
'docs_url': 'https://www.home-assistant.io/components/twilio/'
}
)
18 changes: 18 additions & 0 deletions homeassistant/components/twilio/strings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"config": {
"title": "Twilio",
"step": {
"user": {
"title": "Set up the Twilio Webhook",
"description": "Are you sure you want to set up Twilio?"
}
},
"abort": {
"one_instance_allowed": "Only a single instance is necessary.",
"not_internet_accessible": "Your Home Assistant instance needs to be accessible from the internet to receive Twilio messages."
},
"create_entry": {
"default": "To send events to Home Assistant, you will need to setup [Webhooks with Twilio]({twilio_url}).\n\nFill in the following info:\n\n- URL: `{webhook_url}`\n- Method: POST\n- Content Type: application/x-www-form-urlencoded\n\nSee [the documentation]({docs_url}) on how to configure automations to handle incoming data."
}
}
}
1 change: 1 addition & 0 deletions homeassistant/config_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ async def async_step_discovery(info):
'smhi',
'sonos',
'tradfri',
'twilio',
'unifi',
'upnp',
'zone',
Expand Down
1 change: 1 addition & 0 deletions tests/components/twilio/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Tests for the Twilio component."""
41 changes: 41 additions & 0 deletions tests/components/twilio/test_init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Test the init file of Twilio."""
from unittest.mock import patch

from homeassistant import data_entry_flow
from homeassistant.components import twilio
from homeassistant.core import callback
from tests.common import MockDependency


@MockDependency('twilio', 'rest')
@MockDependency('twilio', 'twiml')
async def test_config_flow_registers_webhook(hass, aiohttp_client):
"""Test setting up Twilio and sending webhook."""
with patch('homeassistant.util.get_local_ip', return_value='example.com'):
result = await hass.config_entries.flow.async_init('twilio', context={
'source': 'user'
})
assert result['type'] == data_entry_flow.RESULT_TYPE_FORM, result

result = await hass.config_entries.flow.async_configure(
result['flow_id'], {})
assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
webhook_id = result['result'].data['webhook_id']

twilio_events = []

@callback
def handle_event(event):
"""Handle Twilio event."""
twilio_events.append(event)

hass.bus.async_listen(twilio.RECEIVED_DATA, handle_event)

client = await aiohttp_client(hass.http.app)
await client.post('/api/webhook/{}'.format(webhook_id), data={
'hello': 'twilio'
})

assert len(twilio_events) == 1
assert twilio_events[0].data['webhook_id'] == webhook_id
assert twilio_events[0].data['hello'] == 'twilio'