From 9a075778fe4be60fdcb5078bebe44eb77a113f2d Mon Sep 17 00:00:00 2001 From: Omar Usman Date: Wed, 21 Jun 2017 15:09:49 +0800 Subject: [PATCH 1/8] Add ClickSend notify service. --- homeassistant/components/notify/clicksend.py | 71 ++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 homeassistant/components/notify/clicksend.py diff --git a/homeassistant/components/notify/clicksend.py b/homeassistant/components/notify/clicksend.py new file mode 100644 index 0000000000000..95dbbf33c9fe4 --- /dev/null +++ b/homeassistant/components/notify/clicksend.py @@ -0,0 +1,71 @@ +""" +Clicksend platform for notify component. +For more details about this platform, please refer to the documentation at +https://clicksend.com/help +""" + +# Import dependencies. +import logging +import requests +import json +import base64 + +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +from homeassistant.components.notify import ( + PLATFORM_SCHEMA, BaseNotificationService) + +# Get logger instance. +_LOGGER = logging.getLogger(__name__) + +# Set platform parameters. +CONF_API_URL = 'https://rest.clicksend.com/v3/sms/send' +CONF_USERNAME = 'username' +CONF_API_KEY = 'api_key' +CONF_TO_NO = 'to_no' + +# Validate parameter schema. +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_USERNAME): cv.string, + vol.Required(CONF_API_KEY): cv.string, + vol.Required(CONF_TO_NO): cv.string, +}) + +# Define service instance. +def get_service(hass, config, discovery_info=None): + + # Set notification service instance. + return ClicksendNotificationService(config[CONF_USERNAME], config[CONF_API_KEY], config[CONF_TO_NO]) + +# Implement the notification service. +class ClicksendNotificationService(BaseNotificationService): + """Implementation of a notification service for the Twitter service.""" + + def __init__(self, username, api_key, to_no): + + # Set variables. + self.username = username + self.api_key = api_key + self.to_no = to_no + + def send_message(self, message="", **kwargs): + + # Send request. + auth = self.username + ':' + self.api_key + auth = base64.b64encode(bytes(auth, 'utf-8')) + auth = 'Basic ' + auth.decode('utf-8') + + data = {'messages': [{'source': 'hass.notify', 'from': self.to_no, 'to': self.to_no, 'body': message}]} + headers = {'Content-type': 'application/json', 'Authorization': auth} + + resp = requests.post(CONF_API_URL, data=json.dumps(data), headers=headers) + + obj = json.loads(resp.text) + response_msg = obj['response_msg'] + response_code = obj['response_code'] + + # Display error when failed. + if resp.status_code != 200: + _LOGGER.error("Error %s : %s (Code %s)", resp.status_code, + response_msg, response_code) \ No newline at end of file From 9f2ebb886285ea69ff2ce1c4130c33d259daa20c Mon Sep 17 00:00:00 2001 From: Omar Usman Date: Thu, 22 Jun 2017 12:23:25 +0800 Subject: [PATCH 2/8] PR #8135 changes. - Some code spacing fixes. - Add timeout to requests. - Change doc url. - Use const.py as much as possible. - Check credentials to determine if setup fails or not. - Add docstrings. - Use string formatting. --- homeassistant/components/notify/clicksend.py | 65 ++++++++++++-------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/homeassistant/components/notify/clicksend.py b/homeassistant/components/notify/clicksend.py index 95dbbf33c9fe4..7feb42113e9f1 100644 --- a/homeassistant/components/notify/clicksend.py +++ b/homeassistant/components/notify/clicksend.py @@ -1,7 +1,7 @@ """ Clicksend platform for notify component. For more details about this platform, please refer to the documentation at -https://clicksend.com/help +https://home-assistant.io/components/notify.clicksend/ """ # Import dependencies. @@ -12,6 +12,8 @@ import voluptuous as vol +from homeassistant.const import (CONF_USERNAME, CONF_API_KEY, CONF_RECIPIENT, + HTTP_HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON, HTTP_BASIC_AUTHENTICATION) import homeassistant.helpers.config_validation as cv from homeassistant.components.notify import ( PLATFORM_SCHEMA, BaseNotificationService) @@ -20,46 +22,45 @@ _LOGGER = logging.getLogger(__name__) # Set platform parameters. -CONF_API_URL = 'https://rest.clicksend.com/v3/sms/send' -CONF_USERNAME = 'username' -CONF_API_KEY = 'api_key' -CONF_TO_NO = 'to_no' +BASE_API_URL = 'https://rest.clicksend.com/v3' # Validate parameter schema. PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_API_KEY): cv.string, - vol.Required(CONF_TO_NO): cv.string, + vol.Required(CONF_RECIPIENT): cv.string, }) -# Define service instance. + def get_service(hass, config, discovery_info=None): + """Get the ClickSend notification service.""" + if _authenticate(config) is False: + _LOGGER.exception("You are not authorized to access ClickSend.") + return None - # Set notification service instance. - return ClicksendNotificationService(config[CONF_USERNAME], config[CONF_API_KEY], config[CONF_TO_NO]) + return ClicksendNotificationService(config) -# Implement the notification service. -class ClicksendNotificationService(BaseNotificationService): - """Implementation of a notification service for the Twitter service.""" - def __init__(self, username, api_key, to_no): +class ClicksendNotificationService(BaseNotificationService): + """Implementation of a notification service for the ClickSend service.""" - # Set variables. - self.username = username - self.api_key = api_key - self.to_no = to_no + def __init__(self, config): + """Initialize the service.""" + self.username = config.get(CONF_USERNAME) + self.api_key = config.get(CONF_API_KEY) + self.recipient = config.get(CONF_RECIPIENT) def send_message(self, message="", **kwargs): + """Send a message to a user.""" + data = ({'messages': [{'source': 'hass.notify', 'from': self.recipient, + 'to': self.recipient, 'body': message}]}) - # Send request. - auth = self.username + ':' + self.api_key - auth = base64.b64encode(bytes(auth, 'utf-8')) - auth = 'Basic ' + auth.decode('utf-8') + headers = {HTTP_HEADER_CONTENT_TYPE: CONTENT_TYPE_JSON} - data = {'messages': [{'source': 'hass.notify', 'from': self.to_no, 'to': self.to_no, 'body': message}]} - headers = {'Content-type': 'application/json', 'Authorization': auth} + api_url = "{}/sms/send".format(BASE_API_URL) - resp = requests.post(CONF_API_URL, data=json.dumps(data), headers=headers) + resp = requests.post(api_url, data=json.dumps(data), headers=headers, + auth=(self.username, self.api_key), timeout=5) obj = json.loads(resp.text) response_msg = obj['response_msg'] @@ -68,4 +69,18 @@ def send_message(self, message="", **kwargs): # Display error when failed. if resp.status_code != 200: _LOGGER.error("Error %s : %s (Code %s)", resp.status_code, - response_msg, response_code) \ No newline at end of file + response_msg, response_code) + + +def _authenticate(config): + """Authenticate with ClickSend.""" + api_url = '{}/account'.format(BASE_API_URL) + headers = {HTTP_HEADER_CONTENT_TYPE: CONTENT_TYPE_JSON} + + resp = requests.get(api_url, auth=(config.get(CONF_USERNAME), + config.get(CONF_API_KEY)), timeout=5) + + if resp.status_code != 200: + return False + + return True From 918ac7ffa019920abd5bcb92913f46f14e6701a3 Mon Sep 17 00:00:00 2001 From: Omar Usman Date: Thu, 22 Jun 2017 12:37:40 +0800 Subject: [PATCH 3/8] PR #8135 changes. - Remove unused variables. - Continuation line under-indented for visual indent. --- homeassistant/components/notify/clicksend.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/notify/clicksend.py b/homeassistant/components/notify/clicksend.py index 7feb42113e9f1..8907c067d77a9 100644 --- a/homeassistant/components/notify/clicksend.py +++ b/homeassistant/components/notify/clicksend.py @@ -12,8 +12,9 @@ import voluptuous as vol -from homeassistant.const import (CONF_USERNAME, CONF_API_KEY, CONF_RECIPIENT, - HTTP_HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON, HTTP_BASIC_AUTHENTICATION) +from homeassistant.const import (CONF_USERNAME, CONF_API_KEY, + CONF_RECIPIENT,HTTP_HEADER_CONTENT_TYPE, + CONTENT_TYPE_JSON) import homeassistant.helpers.config_validation as cv from homeassistant.components.notify import ( PLATFORM_SCHEMA, BaseNotificationService) @@ -60,7 +61,7 @@ def send_message(self, message="", **kwargs): api_url = "{}/sms/send".format(BASE_API_URL) resp = requests.post(api_url, data=json.dumps(data), headers=headers, - auth=(self.username, self.api_key), timeout=5) + auth=(self.username, self.api_key), timeout=5) obj = json.loads(resp.text) response_msg = obj['response_msg'] @@ -71,13 +72,14 @@ def send_message(self, message="", **kwargs): _LOGGER.error("Error %s : %s (Code %s)", resp.status_code, response_msg, response_code) - + def _authenticate(config): """Authenticate with ClickSend.""" api_url = '{}/account'.format(BASE_API_URL) headers = {HTTP_HEADER_CONTENT_TYPE: CONTENT_TYPE_JSON} - resp = requests.get(api_url, auth=(config.get(CONF_USERNAME), + resp = requests.get(api_url, headers=headers, + auth=(config.get(CONF_USERNAME), config.get(CONF_API_KEY)), timeout=5) if resp.status_code != 200: From 75eaf3d202c8b825419afc10d9d23864fdaaad62 Mon Sep 17 00:00:00 2001 From: Omar Usman Date: Thu, 22 Jun 2017 12:48:32 +0800 Subject: [PATCH 4/8] PR #8135 changes. - Format code based on PEP8. --- homeassistant/components/notify/clicksend.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/notify/clicksend.py b/homeassistant/components/notify/clicksend.py index 8907c067d77a9..2e5068f4c70c8 100644 --- a/homeassistant/components/notify/clicksend.py +++ b/homeassistant/components/notify/clicksend.py @@ -13,7 +13,7 @@ import voluptuous as vol from homeassistant.const import (CONF_USERNAME, CONF_API_KEY, - CONF_RECIPIENT,HTTP_HEADER_CONTENT_TYPE, + CONF_RECIPIENT, HTTP_HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON) import homeassistant.helpers.config_validation as cv from homeassistant.components.notify import ( @@ -54,7 +54,7 @@ def __init__(self, config): def send_message(self, message="", **kwargs): """Send a message to a user.""" data = ({'messages': [{'source': 'hass.notify', 'from': self.recipient, - 'to': self.recipient, 'body': message}]}) + 'to': self.recipient, 'body': message}]}) headers = {HTTP_HEADER_CONTENT_TYPE: CONTENT_TYPE_JSON} @@ -72,7 +72,7 @@ def send_message(self, message="", **kwargs): _LOGGER.error("Error %s : %s (Code %s)", resp.status_code, response_msg, response_code) - + def _authenticate(config): """Authenticate with ClickSend.""" api_url = '{}/account'.format(BASE_API_URL) @@ -80,7 +80,7 @@ def _authenticate(config): resp = requests.get(api_url, headers=headers, auth=(config.get(CONF_USERNAME), - config.get(CONF_API_KEY)), timeout=5) + config.get(CONF_API_KEY)), timeout=5) if resp.status_code != 200: return False From 55d0db0324010607269ed5186029e7c4aa77ae26 Mon Sep 17 00:00:00 2001 From: Omar Usman Date: Thu, 22 Jun 2017 12:54:54 +0800 Subject: [PATCH 5/8] PR #8135 changes. - Remove unused base64 dependency. --- homeassistant/components/notify/clicksend.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/notify/clicksend.py b/homeassistant/components/notify/clicksend.py index 2e5068f4c70c8..bdd837877d579 100644 --- a/homeassistant/components/notify/clicksend.py +++ b/homeassistant/components/notify/clicksend.py @@ -8,7 +8,6 @@ import logging import requests import json -import base64 import voluptuous as vol From 0dc0ee2068a21929efef30dbb8c4bab157d0944a Mon Sep 17 00:00:00 2001 From: Omar Usman Date: Thu, 22 Jun 2017 15:20:54 +0800 Subject: [PATCH 6/8] PR #8135 changes. - Fix: D205: 1 blank line required between summary line and description (found 0) - Fix: standard import "import json" comes before "import requests" --- homeassistant/components/notify/clicksend.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/notify/clicksend.py b/homeassistant/components/notify/clicksend.py index bdd837877d579..00c311e000159 100644 --- a/homeassistant/components/notify/clicksend.py +++ b/homeassistant/components/notify/clicksend.py @@ -1,13 +1,14 @@ """ Clicksend platform for notify component. + For more details about this platform, please refer to the documentation at https://home-assistant.io/components/notify.clicksend/ """ # Import dependencies. import logging -import requests import json +import requests import voluptuous as vol From 80aa6637c4bf769411372c3fae363cb7497deecf Mon Sep 17 00:00:00 2001 From: Omar Usman Date: Thu, 22 Jun 2017 17:42:32 +0800 Subject: [PATCH 7/8] PR #8135 changes. - Add files to .coveragerc --- .coveragerc | 1 + 1 file changed, 1 insertion(+) diff --git a/.coveragerc b/.coveragerc index f2d34fe50e7b5..235f6db1bf989 100644 --- a/.coveragerc +++ b/.coveragerc @@ -342,6 +342,7 @@ omit = homeassistant/components/notify/aws_sns.py homeassistant/components/notify/aws_sqs.py homeassistant/components/notify/ciscospark.py + homeassistant/components/notify/clicksend.py homeassistant/components/notify/discord.py homeassistant/components/notify/facebook.py homeassistant/components/notify/free_mobile.py From 8e870b9486651a70acf79f14641ed92904506ed4 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Fri, 23 Jun 2017 22:20:05 +0200 Subject: [PATCH 8/8] Remove obvious comments and set constant --- homeassistant/components/notify/clicksend.py | 26 +++++++------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/notify/clicksend.py b/homeassistant/components/notify/clicksend.py index 00c311e000159..663f689a9752d 100644 --- a/homeassistant/components/notify/clicksend.py +++ b/homeassistant/components/notify/clicksend.py @@ -4,28 +4,25 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/notify.clicksend/ """ - -# Import dependencies. -import logging import json +import logging import requests import voluptuous as vol -from homeassistant.const import (CONF_USERNAME, CONF_API_KEY, - CONF_RECIPIENT, HTTP_HEADER_CONTENT_TYPE, - CONTENT_TYPE_JSON) import homeassistant.helpers.config_validation as cv +from homeassistant.const import ( + CONF_USERNAME, CONF_API_KEY, CONF_RECIPIENT, HTTP_HEADER_CONTENT_TYPE, + CONTENT_TYPE_JSON) from homeassistant.components.notify import ( PLATFORM_SCHEMA, BaseNotificationService) -# Get logger instance. _LOGGER = logging.getLogger(__name__) -# Set platform parameters. BASE_API_URL = 'https://rest.clicksend.com/v3' -# Validate parameter schema. +HEADERS = {HTTP_HEADER_CONTENT_TYPE: CONTENT_TYPE_JSON} + PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_API_KEY): cv.string, @@ -36,7 +33,7 @@ def get_service(hass, config, discovery_info=None): """Get the ClickSend notification service.""" if _authenticate(config) is False: - _LOGGER.exception("You are not authorized to access ClickSend.") + _LOGGER.exception("You are not authorized to access ClickSend") return None return ClicksendNotificationService(config) @@ -56,18 +53,15 @@ def send_message(self, message="", **kwargs): data = ({'messages': [{'source': 'hass.notify', 'from': self.recipient, 'to': self.recipient, 'body': message}]}) - headers = {HTTP_HEADER_CONTENT_TYPE: CONTENT_TYPE_JSON} - api_url = "{}/sms/send".format(BASE_API_URL) - resp = requests.post(api_url, data=json.dumps(data), headers=headers, + resp = requests.post(api_url, data=json.dumps(data), headers=HEADERS, auth=(self.username, self.api_key), timeout=5) obj = json.loads(resp.text) response_msg = obj['response_msg'] response_code = obj['response_code'] - # Display error when failed. if resp.status_code != 200: _LOGGER.error("Error %s : %s (Code %s)", resp.status_code, response_msg, response_code) @@ -76,9 +70,7 @@ def send_message(self, message="", **kwargs): def _authenticate(config): """Authenticate with ClickSend.""" api_url = '{}/account'.format(BASE_API_URL) - headers = {HTTP_HEADER_CONTENT_TYPE: CONTENT_TYPE_JSON} - - resp = requests.get(api_url, headers=headers, + resp = requests.get(api_url, headers=HEADERS, auth=(config.get(CONF_USERNAME), config.get(CONF_API_KEY)), timeout=5)