From 397ad4de0fd855daa012ac8f85108fe9a2704be0 Mon Sep 17 00:00:00 2001
From: Chris Caron <lead2gold@gmail.com>
Date: Tue, 1 Sep 2020 21:46:21 -0400
Subject: [PATCH] LaMetric Time supports icon= for custom defined ones (#287)

---
 apprise/plugins/NotifyLametric.py | 37 ++++++++++++++++++++++++++++---
 test/test_rest_plugins.py         | 26 ++++++++++++++++++++++
 2 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/apprise/plugins/NotifyLametric.py b/apprise/plugins/NotifyLametric.py
index a17eeb60..a8938e65 100644
--- a/apprise/plugins/NotifyLametric.py
+++ b/apprise/plugins/NotifyLametric.py
@@ -55,6 +55,8 @@
 
 # A great source for the icon reference:
 # - https://developer.lametric.com/icons
+
+import re
 import six
 import requests
 from json import dumps
@@ -383,6 +385,10 @@ class NotifyLametric(NotifyBase):
             'values': LAMETRIC_PRIORITIES,
             'default': LametricPriority.INFO,
         },
+        'icon': {
+            'name': _('Custom Icon'),
+            'type': 'string',
+        },
         'icon_type': {
             'name': _('Icon Type'),
             'type': 'choice:string',
@@ -409,7 +415,8 @@ class NotifyLametric(NotifyBase):
     })
 
     def __init__(self, apikey=None, client_id=None, secret=None, priority=None,
-                 icon_type=None, sound=None, mode=None, cycles=None, **kwargs):
+                 icon=None, icon_type=None, sound=None, mode=None,
+                 cycles=None, **kwargs):
         """
         Initialize LaMetric Object
         """
@@ -465,6 +472,11 @@ class NotifyLametric(NotifyBase):
         else:
             self.priority = priority
 
+        # assign our icon (if it was defined); we also eliminate
+        # any hashtag (#) entries that might be present
+        self.icon = re.search(r'[#\s]*(?P<value>.+?)\s*$', icon) \
+            .group('value') if isinstance(icon, six.string_types) else None
+
         if icon_type not in LAMETRIC_ICON_TYPES:
             self.icon_type = self.template_args['icon_type']['default']
 
@@ -530,12 +542,18 @@ class NotifyLametric(NotifyBase):
             self.logger.warning(
                 'LaMetric cycle settings is unavailable in Cloud mode')
 
+        # Assign our icon if the user specified a custom one, otherwise
+        # choose from our pre-set list (based on notify_type)
+        icon = self.icon if self.icon \
+            else self.lametric_icon_id_mapping[notify_type]
+
+        # Our Payload
         # Cloud Notifications don't have as much functionality
         # You can not set priority and/or sound
         payload = {
             "frames": [
                 {
-                    "icon": self.lametric_icon_id_mapping[notify_type],
+                    "icon": icon,
                     "text": body,
                 }
             ]
@@ -552,6 +570,11 @@ class NotifyLametric(NotifyBase):
         Return URL and Payload for Device directed requests
         """
 
+        # Assign our icon if the user specified a custom one, otherwise
+        # choose from our pre-set list (based on notify_type)
+        icon = self.icon if self.icon \
+            else self.lametric_icon_id_mapping[notify_type]
+
         # Our Payload
         payload = {
             # Priority of the message
@@ -573,7 +596,7 @@ class NotifyLametric(NotifyBase):
                 "cycles": self.cycles,
                 "frames": [
                     {
-                        "icon": self.lametric_icon_id_mapping[notify_type],
+                        "icon": icon,
                         "text": body,
                     }
                 ]
@@ -701,6 +724,10 @@ class NotifyLametric(NotifyBase):
         # Extend our parameters
         params.update(self.url_parameters(privacy=privacy, *args, **kwargs))
 
+        if self.icon:
+            # Assign our icon IF one was specified
+            params['icon'] = self.icon
+
         if self.mode == LametricMode.CLOUD:
             # Upstream/LaMetric App Return
             return '{schema}://{client_id}@{secret}/?{params}'.format(
@@ -775,6 +802,10 @@ class NotifyLametric(NotifyBase):
         if 'priority' in results['qsd'] and len(results['qsd']['priority']):
             results['priority'] = results['qsd']['priority'].strip().lower()
 
+        # Icon Type
+        if 'icon' in results['qsd'] and len(results['qsd']['icon']):
+            results['icon'] = results['qsd']['icon'].strip().lower()
+
         # Icon Type
         if 'icon_type' in results['qsd'] and len(results['qsd']['icon_type']):
             results['icon_type'] = results['qsd']['icon_type'].strip().lower()
diff --git a/test/test_rest_plugins.py b/test/test_rest_plugins.py
index 1a4064b1..bfb0f03b 100644
--- a/test/test_rest_plugins.py
+++ b/test/test_rest_plugins.py
@@ -1353,6 +1353,26 @@ TEST_URLS = (
         # Invalid priority just produce warnings... object still loads
         'instance': plugins.NotifyLametric,
     }),
+    ('lametric://{}@192.168.1.2/?icon=230'.format(UUID4), {
+        # Our custom icon by it's ID
+        'instance': plugins.NotifyLametric,
+    }),
+    ('lametrics://{}@192.168.1.2/?icon=#230'.format(UUID4), {
+        # Our custom icon by it's ID; the hashtag at the front is ignored
+        'instance': plugins.NotifyLametric,
+    }),
+    ('lametric://{}@192.168.1.2/?icon=Heart'.format(UUID4), {
+        # Our custom icon; the hashtag at the front is ignored
+        'instance': plugins.NotifyLametric,
+    }),
+    ('lametric://{}@192.168.1.2/?icon=#'.format(UUID4), {
+        # a hashtag and nothing else
+        'instance': plugins.NotifyLametric,
+    }),
+    ('lametric://{}@192.168.1.2/?icon=#%20%20%20'.format(UUID4), {
+        # a hashtag and some spaces
+        'instance': plugins.NotifyLametric,
+    }),
     ('lametric://{}@192.168.1.3/?cycles=2'.format(UUID4), {
         # Cycles changed
         'instance': plugins.NotifyLametric,
@@ -1374,6 +1394,12 @@ TEST_URLS = (
         # Our expected url(privacy=True) startswith() response:
         'privacy_url': 'lametric://8...2@****/',
     }),
+    ('lametric://{}@{}/'.format(
+        UUID4, 'YWosnkdnoYREsdogfoSDff734kjsfbweo7r434597FYODIoicosdonnreiuhvd'
+               'ciuhouerhohcd8sds89fdRw==?icon=Heart'), {
+        # Cloude mode with the icon over-ride
+        'instance': plugins.NotifyLametric,
+    }),
     ('lametric://{}@example.com/'.format(UUID4), {
         'instance': plugins.NotifyLametric,
         # force a failure