summaryrefslogtreecommitdiffhomepage
path: root/libs/apprise/plugins/NotifyTwilio.py
diff options
context:
space:
mode:
Diffstat (limited to 'libs/apprise/plugins/NotifyTwilio.py')
-rw-r--r--libs/apprise/plugins/NotifyTwilio.py89
1 files changed, 45 insertions, 44 deletions
diff --git a/libs/apprise/plugins/NotifyTwilio.py b/libs/apprise/plugins/NotifyTwilio.py
index 4ab19713f..883cc50ba 100644
--- a/libs/apprise/plugins/NotifyTwilio.py
+++ b/libs/apprise/plugins/NotifyTwilio.py
@@ -40,22 +40,18 @@
# or consider purchasing a short-code from here:
# https://www.twilio.com/docs/glossary/what-is-a-short-code
#
-import re
import requests
from json import loads
from .NotifyBase import NotifyBase
from ..URLBase import PrivacyMode
from ..common import NotifyType
-from ..utils import parse_list
+from ..utils import is_phone_no
+from ..utils import parse_phone_no
from ..utils import validate_regex
from ..AppriseLocale import gettext_lazy as _
-# Some Phone Number Detection
-IS_PHONE_NO = re.compile(r'^\+?(?P<phone>[0-9\s)(+-]+)\s*$')
-
-
class NotifyTwilio(NotifyBase):
"""
A wrapper for Twilio Notifications
@@ -112,7 +108,7 @@ class NotifyTwilio(NotifyBase):
'type': 'string',
'private': True,
'required': True,
- 'regex': (r'^[a-f0-9]+$', 'i'),
+ 'regex': (r'^[a-z0-9]+$', 'i'),
},
'from_phone': {
'name': _('From Phone No'),
@@ -154,10 +150,16 @@ class NotifyTwilio(NotifyBase):
'token': {
'alias_of': 'auth_token',
},
+ 'apikey': {
+ 'name': _('API Key'),
+ 'type': 'string',
+ 'private': True,
+ 'regex': (r'^SK[a-f0-9]+$', 'i'),
+ },
})
def __init__(self, account_sid, auth_token, source, targets=None,
- **kwargs):
+ apikey=None, ** kwargs):
"""
Initialize Twilio Object
"""
@@ -181,17 +183,19 @@ class NotifyTwilio(NotifyBase):
self.logger.warning(msg)
raise TypeError(msg)
- # The Source Phone # and/or short-code
- self.source = source
+ # The API Key associated with the account (optional)
+ self.apikey = validate_regex(
+ apikey, *self.template_args['apikey']['regex'])
- if not IS_PHONE_NO.match(self.source):
+ result = is_phone_no(source, min_len=5)
+ if not result:
msg = 'The Account (From) Phone # or Short-code specified ' \
'({}) is invalid.'.format(source)
self.logger.warning(msg)
raise TypeError(msg)
- # Tidy source
- self.source = re.sub(r'[^\d]+', '', self.source)
+ # Store The Source Phone # and/or short-code
+ self.source = result['full']
if len(self.source) < 11 or len(self.source) > 14:
# https://www.twilio.com/docs/glossary/what-is-a-short-code
@@ -213,37 +217,18 @@ class NotifyTwilio(NotifyBase):
# Parse our targets
self.targets = list()
- for target in parse_list(targets):
+ for target in parse_phone_no(targets):
# Validate targets and drop bad ones:
- result = IS_PHONE_NO.match(target)
- if result:
- # Further check our phone # for it's digit count
- # if it's less than 10, then we can assume it's
- # a poorly specified phone no and spit a warning
- result = ''.join(re.findall(r'\d+', result.group('phone')))
- if len(result) < 11 or len(result) > 14:
- self.logger.warning(
- 'Dropped invalid phone # '
- '({}) specified.'.format(target),
- )
- continue
-
- # store valid phone number
- self.targets.append('+{}'.format(result))
+ result = is_phone_no(target)
+ if not result:
+ self.logger.warning(
+ 'Dropped invalid phone # '
+ '({}) specified.'.format(target),
+ )
continue
- self.logger.warning(
- 'Dropped invalid phone # '
- '({}) specified.'.format(target),
- )
-
- if not self.targets:
- if len(self.source) in (5, 6):
- # raise a warning since we're a short-code. We need
- # a number to message
- msg = 'There are no valid Twilio targets to notify.'
- self.logger.warning(msg)
- raise TypeError(msg)
+ # store valid phone number
+ self.targets.append('+{}'.format(result['full']))
return
@@ -252,6 +237,14 @@ class NotifyTwilio(NotifyBase):
Perform Twilio Notification
"""
+ if not self.targets:
+ if len(self.source) in (5, 6):
+ # Generate a warning since we're a short-code. We need
+ # a number to message at minimum
+ self.logger.warning(
+ 'There are no valid Twilio targets to notify.')
+ return False
+
# error tracking (used for function return)
has_error = False
@@ -276,8 +269,8 @@ class NotifyTwilio(NotifyBase):
# Create a copy of the targets list
targets = list(self.targets)
- # Set up our authentication
- auth = (self.account_sid, self.auth_token)
+ # Set up our authentication. Prefer the API Key if provided.
+ auth = (self.apikey or self.account_sid, self.auth_token)
if len(targets) == 0:
# No sources specified, use our own phone no
@@ -371,6 +364,10 @@ class NotifyTwilio(NotifyBase):
# Our URL parameters
params = self.url_parameters(privacy=privacy, *args, **kwargs)
+ if self.apikey is not None:
+ # apikey specified; pass it back on the url
+ params['apikey'] = self.apikey
+
return '{schema}://{sid}:{token}@{source}/{targets}/?{params}'.format(
schema=self.secure_protocol,
sid=self.pprint(
@@ -417,6 +414,10 @@ class NotifyTwilio(NotifyBase):
results['account_sid'] = \
NotifyTwilio.unquote(results['qsd']['sid'])
+ # API Key
+ if 'apikey' in results['qsd'] and len(results['qsd']['apikey']):
+ results['apikey'] = results['qsd']['apikey']
+
# Support the 'from' and 'source' variable so that we can support
# targets this way too.
# The 'from' makes it easier to use yaml configuration
@@ -431,6 +432,6 @@ class NotifyTwilio(NotifyBase):
# The 'to' makes it easier to use yaml configuration
if 'to' in results['qsd'] and len(results['qsd']['to']):
results['targets'] += \
- NotifyTwilio.parse_list(results['qsd']['to'])
+ NotifyTwilio.parse_phone_no(results['qsd']['to'])
return results