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:
parent
a1c914dfeb
commit
bc8d323bdd
3 changed files with 62 additions and 9 deletions
|
@ -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(
|
||||
|
|
|
@ -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."""
|
||||
|
|
|
@ -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" }'
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue