Add image support to hangouts notifications (#16560)

* add image to services.yaml

* add image support

Add image support to hangouts notification.

* fix indents

* fix line length

* Add data schema

forgot schema

* fix linelength

* use is_allowed_path and better file error handling

* elif not else if

* fix logger error

* fixes

* fix travis errors/warnings

* remove trailing whitespace

* fix travis pylint naming

* new async style

* removed unused async_timeout

* change to image_file/url (#3)

* change to image_file/url

* removed whitespace

* forgot to remove unused urlparse import

* image_file/url in service help
This commit is contained in:
Tommy Jonsson 2018-09-25 15:04:43 +02:00 committed by Pascal Vizeli
parent a1c914dfeb
commit bc8d323bdd
3 changed files with 62 additions and 9 deletions

View file

@ -3,7 +3,8 @@ import logging
import voluptuous as vol
from homeassistant.components.notify import ATTR_MESSAGE, ATTR_TARGET
from homeassistant.components.notify \
import ATTR_MESSAGE, ATTR_TARGET, ATTR_DATA
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger('homeassistant.components.hangouts')
@ -56,10 +57,15 @@ MESSAGE_SEGMENT_SCHEMA = vol.Schema({
vol.Optional('parse_str'): cv.boolean,
vol.Optional('link_target'): cv.string
})
MESSAGE_DATA_SCHEMA = vol.Schema({
vol.Optional('image_file'): cv.string,
vol.Optional('image_url'): cv.string
})
MESSAGE_SCHEMA = vol.Schema({
vol.Required(ATTR_TARGET): [TARGETS_SCHEMA],
vol.Required(ATTR_MESSAGE): [MESSAGE_SEGMENT_SCHEMA]
vol.Required(ATTR_MESSAGE): [MESSAGE_SEGMENT_SCHEMA],
vol.Optional(ATTR_DATA): MESSAGE_DATA_SCHEMA
})
INTENT_SCHEMA = vol.All(

View file

@ -1,10 +1,13 @@
"""The Hangouts Bot."""
import io
import logging
import asyncio
import aiohttp
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers import dispatcher, intent
from .const import (
ATTR_MESSAGE, ATTR_TARGET, CONF_CONVERSATIONS, DOMAIN,
ATTR_MESSAGE, ATTR_TARGET, ATTR_DATA, CONF_CONVERSATIONS, DOMAIN,
EVENT_HANGOUTS_CONNECTED, EVENT_HANGOUTS_CONVERSATIONS_CHANGED,
EVENT_HANGOUTS_DISCONNECTED, EVENT_HANGOUTS_MESSAGE_RECEIVED,
CONF_MATCHERS, CONF_CONVERSATION_ID,
@ -146,7 +149,8 @@ class HangoutsBot:
is_error and conv_id in self._error_suppressed_conv_ids):
await self._async_send_message(
[{'text': message, 'parse_str': True}],
[{CONF_CONVERSATION_ID: conv_id}])
[{CONF_CONVERSATION_ID: conv_id}],
None)
async def _async_process(self, intents, text, conv_id):
"""Detect a matching intent."""
@ -203,7 +207,7 @@ class HangoutsBot:
"""Run once when Home Assistant stops."""
await self.async_disconnect()
async def _async_send_message(self, message, targets):
async def _async_send_message(self, message, targets, data):
conversations = []
for target in targets:
conversation = None
@ -233,10 +237,48 @@ class HangoutsBot:
del segment['parse_str']
messages.append(ChatMessageSegment(**segment))
image_file = None
if data:
if data.get('image_url'):
uri = data.get('image_url')
try:
websession = async_get_clientsession(self.hass)
async with websession.get(uri, timeout=5) as response:
if response.status != 200:
_LOGGER.error(
'Fetch image failed, %s, %s',
response.status,
response
)
image_file = None
else:
image_data = await response.read()
image_file = io.BytesIO(image_data)
image_file.name = "image.png"
except (asyncio.TimeoutError, aiohttp.ClientError) as error:
_LOGGER.error(
'Failed to fetch image, %s',
type(error)
)
image_file = None
elif data.get('image_file'):
uri = data.get('image_file')
if self.hass.config.is_allowed_path(uri):
try:
image_file = open(uri, 'rb')
except IOError as error:
_LOGGER.error(
'Image file I/O error(%s): %s',
error.errno,
error.strerror
)
else:
_LOGGER.error('Path "%s" not allowed', uri)
if not messages:
return False
for conv in conversations:
await conv.send_message(messages)
await conv.send_message(messages, image_file)
async def _async_list_conversations(self):
import hangups
@ -261,7 +303,8 @@ class HangoutsBot:
async def async_handle_send_message(self, service):
"""Handle the send_message service."""
await self._async_send_message(service.data[ATTR_MESSAGE],
service.data[ATTR_TARGET])
service.data[ATTR_TARGET],
service.data[ATTR_DATA])
async def async_handle_update_users_and_conversations(self, _=None):
"""Handle the update_users_and_conversations service."""

View file

@ -10,3 +10,7 @@ send_message:
message:
description: List of message segments, only the "text" field is required in every segment. [Required]
example: '[{"text":"test", "is_bold": false, "is_italic": false, "is_strikethrough": false, "is_underline": false, "parse_str": false, "link_target": "http://google.com"}, ...]'
data:
description: Other options ['image_file' / 'image_url']
example: '{ "image_file": "file" }' or '{ "image_url": "url" }'