Merge pull request #600 from balloob/cleanup-notify

Clean up notifiy component
pull/605/merge
Paulus Schoutsen 2015-11-09 07:32:13 -08:00
commit 2d9a785c18
13 changed files with 143 additions and 252 deletions

View File

@ -51,8 +51,7 @@ def setup(hass, config):
continue
# create platform service
notify_service = notify_implementation.get_service(
hass, {DOMAIN: p_config})
notify_service = notify_implementation.get_service(hass, p_config)
if notify_service is None:
_LOGGER.error("Failed to initialize notification service %s",

View File

@ -20,14 +20,14 @@ _LOGGER = logging.getLogger(__name__)
def get_service(hass, config):
""" Get the file notification service. """
if not validate_config(config,
if not validate_config({DOMAIN: config},
{DOMAIN: ['filename',
'timestamp']},
_LOGGER):
return None
filename = config[DOMAIN]['filename']
timestamp = config[DOMAIN]['timestamp']
filename = config['filename']
timestamp = config['timestamp']
return FileNotificationService(hass, filename, timestamp)

View File

@ -9,6 +9,8 @@ https://home-assistant.io/components/notify.instapush.html
import logging
import json
import requests
from homeassistant.helpers import validate_config
from homeassistant.components.notify import (
DOMAIN, ATTR_TITLE, BaseNotificationService)
@ -21,7 +23,7 @@ _RESOURCE = 'https://api.instapush.im/v1/'
def get_service(hass, config):
""" Get the instapush notification service. """
if not validate_config(config,
if not validate_config({DOMAIN: config},
{DOMAIN: [CONF_API_KEY,
'app_secret',
'event',
@ -29,52 +31,29 @@ def get_service(hass, config):
_LOGGER):
return None
headers = {'x-instapush-appid': config[CONF_API_KEY],
'x-instapush-appsecret': config['app_secret']}
try:
import requests
except ImportError:
_LOGGER.exception(
"Unable to import requests. "
"Did you maybe not install the 'Requests' package?")
response = requests.get(_RESOURCE + 'events/list',
headers=headers).json()
except ValueError:
_LOGGER.error('Unexpected answer from Instapush API.')
return None
# pylint: disable=unused-variable
try:
response = requests.get(_RESOURCE)
if 'error' in response:
_LOGGER.error(response['msg'])
return None
except requests.ConnectionError:
if len([app for app in response if app['title'] == config['event']]) == 0:
_LOGGER.error(
"Connection error "
"Please check if https://instapush.im is available.")
"No app match your given value. "
"Please create an app at https://instapush.im")
return None
instapush = requests.Session()
headers = {'x-instapush-appid': config[DOMAIN][CONF_API_KEY],
'x-instapush-appsecret': config[DOMAIN]['app_secret']}
response = instapush.get(_RESOURCE + 'events/list',
headers=headers)
try:
if response.json()['error']:
_LOGGER.error(response.json()['msg'])
# pylint: disable=bare-except
except:
try:
next(events for events in response.json()
if events['title'] == config[DOMAIN]['event'])
except StopIteration:
_LOGGER.error(
"No event match your given value. "
"Please create an event at https://instapush.im")
else:
return InstapushNotificationService(
config[DOMAIN].get(CONF_API_KEY),
config[DOMAIN]['app_secret'],
config[DOMAIN]['event'],
config[DOMAIN]['tracker']
)
return InstapushNotificationService(
config[CONF_API_KEY], config['app_secret'], config['event'],
config['tracker'])
# pylint: disable=too-few-public-methods
@ -82,9 +61,6 @@ class InstapushNotificationService(BaseNotificationService):
""" Implements notification service for Instapush. """
def __init__(self, api_key, app_secret, event, tracker):
# pylint: disable=no-name-in-module, unused-variable
from requests import Session
self._api_key = api_key
self._app_secret = app_secret
self._event = event
@ -94,8 +70,6 @@ class InstapushNotificationService(BaseNotificationService):
'x-instapush-appsecret': self._app_secret,
'Content-Type': 'application/json'}
self.instapush = Session()
def send_message(self, message="", **kwargs):
""" Send a message to a user. """
@ -104,10 +78,8 @@ class InstapushNotificationService(BaseNotificationService):
data = {"event": self._event,
"trackers": {self._tracker: title + " : " + message}}
response = self.instapush.post(
_RESOURCE + 'post',
data=json.dumps(data),
headers=self._headers)
response = requests.post(_RESOURCE + 'post', data=json.dumps(data),
headers=self._headers)
if response.json()['status'] == 401:
_LOGGER.error(

View File

@ -9,6 +9,8 @@ https://home-assistant.io/components/notify.nma.html
import logging
import xml.etree.ElementTree as ET
import requests
from homeassistant.helpers import validate_config
from homeassistant.components.notify import (
DOMAIN, ATTR_TITLE, BaseNotificationService)
@ -21,31 +23,20 @@ _RESOURCE = 'https://www.notifymyandroid.com/publicapi/'
def get_service(hass, config):
""" Get the NMA notification service. """
if not validate_config(config,
if not validate_config({DOMAIN: config},
{DOMAIN: [CONF_API_KEY]},
_LOGGER):
return None
try:
# pylint: disable=unused-variable
from requests import Session
except ImportError:
_LOGGER.exception(
"Unable to import requests. "
"Did you maybe not install the 'Requests' package?")
return None
nma = Session()
response = nma.get(_RESOURCE + 'verify',
params={"apikey": config[DOMAIN][CONF_API_KEY]})
response = requests.get(_RESOURCE + 'verify',
params={"apikey": config[CONF_API_KEY]})
tree = ET.fromstring(response.content)
if tree[0].tag == 'error':
_LOGGER.error("Wrong API key supplied. %s", tree[0].text)
else:
return NmaNotificationService(config[DOMAIN][CONF_API_KEY])
return None
return NmaNotificationService(config[CONF_API_KEY])
# pylint: disable=too-few-public-methods
@ -53,26 +44,20 @@ class NmaNotificationService(BaseNotificationService):
""" Implements notification service for NMA. """
def __init__(self, api_key):
# pylint: disable=no-name-in-module, unused-variable
from requests import Session
self._api_key = api_key
self._data = {"apikey": self._api_key}
self.nma = Session()
def send_message(self, message="", **kwargs):
""" Send a message to a user. """
title = kwargs.get(ATTR_TITLE)
data = {
"apikey": self._api_key,
"application": 'home-assistant',
"event": kwargs.get(ATTR_TITLE),
"description": message,
"priority": 0,
}
self._data['application'] = 'home-assistant'
self._data['event'] = title
self._data['description'] = message
self._data['priority'] = 0
response = self.nma.get(_RESOURCE + 'notify',
params=self._data)
response = requests.get(_RESOURCE + 'notify', params=data)
tree = ET.fromstring(response.content)
if tree[0].tag == 'error':

View File

@ -8,41 +8,29 @@ https://home-assistant.io/components/notify.pushbullet.html
"""
import logging
from homeassistant.helpers import validate_config
from homeassistant.components.notify import (
DOMAIN, ATTR_TITLE, BaseNotificationService)
from homeassistant.components.notify import ATTR_TITLE, BaseNotificationService
from homeassistant.const import CONF_API_KEY
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['pushbullet.py==0.7.1']
REQUIREMENTS = ['pushbullet.py==0.8.1']
def get_service(hass, config):
""" Get the PushBullet notification service. """
from pushbullet import InvalidKeyError
if not validate_config(config,
{DOMAIN: [CONF_API_KEY]},
_LOGGER):
if CONF_API_KEY not in config:
_LOGGER.error("Unable to find config key '%s'", CONF_API_KEY)
return None
try:
# pylint: disable=unused-variable
from pushbullet import PushBullet, InvalidKeyError # noqa
except ImportError:
_LOGGER.exception(
"Unable to import pushbullet. "
"Did you maybe not install the 'pushbullet.py' package?")
return None
try:
return PushBulletNotificationService(config[DOMAIN][CONF_API_KEY])
return PushBulletNotificationService(config[CONF_API_KEY])
except InvalidKeyError:
_LOGGER.error(
"Wrong API key supplied. "
"Get it at https://www.pushbullet.com/account")
return None
# pylint: disable=too-few-public-methods
@ -50,9 +38,9 @@ class PushBulletNotificationService(BaseNotificationService):
""" Implements notification service for Pushbullet. """
def __init__(self, api_key):
from pushbullet import PushBullet
from pushbullet import Pushbullet
self.pushbullet = PushBullet(api_key)
self.pushbullet = Pushbullet(api_key)
def send_message(self, message="", **kwargs):
""" Send a message to a user. """

View File

@ -21,32 +21,21 @@ _LOGGER = logging.getLogger(__name__)
def get_service(hass, config):
""" Get the pushover notification service. """
if not validate_config(config,
if not validate_config({DOMAIN: config},
{DOMAIN: ['user_key', CONF_API_KEY]},
_LOGGER):
return None
try:
# pylint: disable=no-name-in-module, unused-variable
from pushover import InitError
except ImportError:
_LOGGER.exception(
"Unable to import pushover. "
"Did you maybe not install the 'python-pushover.py' package?")
return None
from pushover import InitError
try:
api_token = config[DOMAIN].get(CONF_API_KEY)
return PushoverNotificationService(
config[DOMAIN]['user_key'],
api_token)
return PushoverNotificationService(config['user_key'],
config[CONF_API_KEY])
except InitError:
_LOGGER.error(
"Wrong API key supplied. "
"Get it at https://pushover.net")
return None
# pylint: disable=too-few-public-methods
@ -54,7 +43,6 @@ class PushoverNotificationService(BaseNotificationService):
""" Implements notification service for Pushover. """
def __init__(self, user_key, api_token):
# pylint: disable=no-name-in-module, unused-variable
from pushover import Client
self._user_key = user_key
self._api_token = api_token
@ -63,11 +51,9 @@ class PushoverNotificationService(BaseNotificationService):
def send_message(self, message="", **kwargs):
""" Send a message to a user. """
# pylint: disable=no-name-in-module
from pushover import RequestError
title = kwargs.get(ATTR_TITLE)
try:
self.pushover.send_message(message, title=title)
self.pushover.send_message(message, title=kwargs.get(ATTR_TITLE))
except RequestError:
_LOGGER.exception("Could not send pushover notification")

View File

@ -0,0 +1,11 @@
notify:
description: Send a notification
fields:
message:
description: Message body of the notification.
example: The garage door has been open for 10 minutes.
title:
description: Optional title for your notification.
example: 'Your Garage Door Friend'

View File

@ -9,8 +9,7 @@ https://home-assistant.io/components/notify.slack.html
import logging
from homeassistant.helpers import validate_config
from homeassistant.components.notify import (
DOMAIN, BaseNotificationService)
from homeassistant.components.notify import DOMAIN, BaseNotificationService
from homeassistant.const import CONF_API_KEY
REQUIREMENTS = ['slacker==0.6.8']
@ -20,34 +19,22 @@ _LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-variable
def get_service(hass, config):
""" Get the slack notification service. """
import slacker
if not validate_config(config,
if not validate_config({DOMAIN: config},
{DOMAIN: ['default_channel', CONF_API_KEY]},
_LOGGER):
return None
try:
# pylint: disable=no-name-in-module, unused-variable
from slacker import Error as SlackError
except ImportError:
_LOGGER.exception(
"Unable to import slacker. "
"Did you maybe not install the 'slacker.py' package?")
return None
try:
api_token = config[DOMAIN].get(CONF_API_KEY)
return SlackNotificationService(
config[DOMAIN]['default_channel'],
api_token)
config['default_channel'],
config[CONF_API_KEY])
except SlackError as ex:
_LOGGER.error(
except slacker.Error:
_LOGGER.exception(
"Slack authentication failed")
_LOGGER.exception(ex)
return None
# pylint: disable=too-few-public-methods
@ -56,6 +43,7 @@ class SlackNotificationService(BaseNotificationService):
def __init__(self, default_channel, api_token):
from slacker import Slacker
self._default_channel = default_channel
self._api_token = api_token
self.slack = Slacker(self._api_token)
@ -63,11 +51,11 @@ class SlackNotificationService(BaseNotificationService):
def send_message(self, message="", **kwargs):
""" Send a message to a user. """
import slacker
from slacker import Error as SlackError
channel = kwargs.get('channel', self._default_channel)
try:
self.slack.chat.post_message(channel, message)
except SlackError as ex:
except slacker.Error:
_LOGGER.exception("Could not send slack notification")
_LOGGER.exception(ex)

View File

@ -20,35 +20,31 @@ _LOGGER = logging.getLogger(__name__)
def get_service(hass, config):
""" Get the mail notification service. """
if not validate_config(config,
{DOMAIN: ['server',
'port',
'sender',
'username',
'password',
'recipient']},
if not validate_config({DOMAIN: config},
{DOMAIN: ['server', 'port', 'sender', 'username',
'password', 'recipient']},
_LOGGER):
return None
smtp_server = config[DOMAIN]['server']
port = int(config[DOMAIN]['port'])
username = config[DOMAIN]['username']
password = config[DOMAIN]['password']
smtp_server = config['server']
port = int(config['port'])
username = config['username']
password = config['password']
starttls = int(config['starttls'])
server = None
try:
server = smtplib.SMTP(smtp_server, port)
server.ehlo()
if int(config[DOMAIN]['starttls']) == 1:
if starttls == 1:
server.starttls()
server.ehlo()
try:
server.login(username, password)
except (smtplib.SMTPException, smtplib.SMTPSenderRefused) as error:
_LOGGER.exception(error,
"Please check your settings.")
except (smtplib.SMTPException, smtplib.SMTPSenderRefused):
_LOGGER.exception("Please check your settings.")
return None
@ -66,18 +62,13 @@ def get_service(hass, config):
return None
if server:
server.quit()
finally:
if server:
server.quit()
return MailNotificationService(
config[DOMAIN]['server'],
config[DOMAIN]['port'],
config[DOMAIN]['sender'],
config[DOMAIN]['starttls'],
config[DOMAIN]['username'],
config[DOMAIN]['password'],
config[DOMAIN]['recipient']
)
smtp_server, port, config['sender'], starttls, username, password,
config['recipient'])
# pylint: disable=too-few-public-methods, too-many-instance-attributes
@ -90,7 +81,7 @@ class MailNotificationService(BaseNotificationService):
self._server = server
self._port = port
self._sender = sender
self.starttls = int(starttls)
self.starttls = starttls
self.username = username
self.password = password
self.recipient = recipient

View File

@ -52,16 +52,14 @@ PRIORITIES = {5: syslog.LOG_EMERG,
def get_service(hass, config):
""" Get the mail notification service. """
if not validate_config(config,
{DOMAIN: ['facility',
'option',
'priority']},
if not validate_config({DOMAIN: config},
{DOMAIN: ['facility', 'option', 'priority']},
_LOGGER):
return None
_facility = FACILITIES.get(config[DOMAIN]['facility'], 40)
_option = OPTIONS.get(config[DOMAIN]['option'], 10)
_priority = PRIORITIES.get(config[DOMAIN]['priority'], -1)
_facility = FACILITIES.get(config['facility'], 40)
_option = OPTIONS.get(config['option'], 10)
_priority = PRIORITIES.get(config['priority'], -1)
return SyslogNotificationService(_facility, _option, _priority)

View File

@ -16,35 +16,27 @@ from homeassistant.const import CONF_API_KEY
_LOGGER = logging.getLogger(__name__)
try:
import telegram
except ImportError:
_LOGGER.exception(
"Unable to import python-telegram-bot. "
"Did you maybe not install the 'python-telegram-bot' package?")
REQUIREMENTS = ['python-telegram-bot==2.8.7']
def get_service(hass, config):
""" Get the Telegram notification service. """
import telegram
if not validate_config(config,
if not validate_config({DOMAIN: config},
{DOMAIN: [CONF_API_KEY, 'chat_id']},
_LOGGER):
return None
try:
bot = telegram.Bot(token=config[DOMAIN][CONF_API_KEY])
bot = telegram.Bot(token=config[CONF_API_KEY])
username = bot.getMe()['username']
_LOGGER.info("Telegram bot is '%s'.", username)
except urllib.error.HTTPError:
_LOGGER.error("Please check your access token.")
return None
return TelegramNotificationService(
config[DOMAIN][CONF_API_KEY],
config[DOMAIN]['chat_id'])
return TelegramNotificationService(config[CONF_API_KEY], config['chat_id'])
# pylint: disable=too-few-public-methods
@ -52,12 +44,15 @@ class TelegramNotificationService(BaseNotificationService):
""" Implements notification service for Telegram. """
def __init__(self, api_key, chat_id):
import telegram
self._api_key = api_key
self._chat_id = chat_id
self.bot = telegram.Bot(token=self._api_key)
def send_message(self, message="", **kwargs):
""" Send a message to a user. """
import telegram
title = kwargs.get(ATTR_TITLE)
@ -65,4 +60,4 @@ class TelegramNotificationService(BaseNotificationService):
self.bot.sendMessage(chat_id=self._chat_id,
text=title + " " + message)
except telegram.error.TelegramError:
_LOGGER.error("Your chat id '%s' is not valid.", self._chat_id)
_LOGGER.exception("Error sending message.")

View File

@ -10,14 +10,6 @@ import logging
_LOGGER = logging.getLogger(__name__)
try:
import sleekxmpp
except ImportError:
_LOGGER.exception(
"Unable to import sleekxmpp. "
"Did you maybe not install the 'SleekXMPP' package?")
from homeassistant.helpers import validate_config
from homeassistant.components.notify import (
DOMAIN, ATTR_TITLE, BaseNotificationService)
@ -28,28 +20,14 @@ REQUIREMENTS = ['sleekxmpp==1.3.1', 'dnspython3==1.12.0']
def get_service(hass, config):
""" Get the Jabber (XMPP) notification service. """
if not validate_config(config,
{DOMAIN: ['sender',
'password',
'recipient']},
if not validate_config({DOMAIN: config},
{DOMAIN: ['sender', 'password', 'recipient']},
_LOGGER):
return None
try:
SendNotificationBot(config[DOMAIN]['sender'] + '/home-assistant',
config[DOMAIN]['password'],
config[DOMAIN]['recipient'],
'')
except ImportError:
_LOGGER.exception(
"Unable to contact jabber server."
"Please check your credentials.")
return None
return XmppNotificationService(config[DOMAIN]['sender'],
config[DOMAIN]['password'],
config[DOMAIN]['recipient'])
return XmppNotificationService(config['sender'],
config['password'],
config['recipient'])
# pylint: disable=too-few-public-methods
@ -65,40 +43,40 @@ class XmppNotificationService(BaseNotificationService):
""" Send a message to a user. """
title = kwargs.get(ATTR_TITLE)
data = title + ": " + message
data = "{}: {}".format(title, message) if title else message
SendNotificationBot(self._sender + '/home-assistant',
self._password,
self._recipient,
data)
send_message(self._sender + '/home-assistant', self._password,
self._recipient, data)
class SendNotificationBot(sleekxmpp.ClientXMPP):
""" Service for sending Jabber (XMPP) messages. """
def send_message(sender, password, recipient, message):
""" Send a message over XMPP. """
import sleekxmpp
def __init__(self, jid, password, recipient, msg):
class SendNotificationBot(sleekxmpp.ClientXMPP):
""" Service for sending Jabber (XMPP) messages. """
super(SendNotificationBot, self).__init__(jid, password)
def __init__(self):
super(SendNotificationBot, self).__init__(sender, password)
logging.basicConfig(level=logging.ERROR)
logging.basicConfig(level=logging.ERROR)
self.recipient = recipient
self.msg = msg
self.use_tls = True
self.use_ipv6 = False
self.add_event_handler('failed_auth', self.check_credentials)
self.add_event_handler('session_start', self.start)
self.connect()
self.process()
self.use_tls = True
self.use_ipv6 = False
self.add_event_handler('failed_auth', self.check_credentials)
self.add_event_handler('session_start', self.start)
self.connect()
self.process(block=False)
def start(self, event):
""" Starts the communication and sends the message. """
self.send_presence()
self.get_roster()
self.send_message(mto=recipient, mbody=message, mtype='chat')
self.disconnect(wait=True)
def start(self, event):
""" Starts the communication and sends the message. """
self.send_presence()
self.get_roster()
self.send_message(mto=self.recipient, mbody=self.msg, mtype='chat')
self.disconnect(wait=True)
def check_credentials(self, event):
"""" Disconnect from the server if credentials are invalid. """
self.disconnect()
def check_credentials(self, event):
"""" Disconnect from the server if credentials are invalid. """
self.disconnect()
SendNotificationBot()

View File

@ -29,7 +29,7 @@ tellcore-py==1.1.2
python-nmap==0.4.3
# PushBullet (notify.pushbullet)
pushbullet.py==0.7.1
pushbullet.py==0.8.1
# Nest Thermostat (thermostat.nest)
python-nest==2.6.0