From ee2aea1b41694a1c9d7691fb4daa157fe3c3d009 Mon Sep 17 00:00:00 2001 From: Chris Caron Date: Thu, 20 Jun 2024 17:30:14 -0400 Subject: [PATCH] url_identifier() function added to all plugins --- apprise/cli.py | 2 +- apprise/plugins/aprs.py | 9 +++ apprise/plugins/bark.py | 12 +++ apprise/plugins/boxcar.py | 9 +++ apprise/plugins/bulksms.py | 13 +++ apprise/plugins/bulkvs.py | 9 +++ apprise/plugins/burstsms.py | 9 +++ apprise/plugins/chantify.py | 9 +++ apprise/plugins/clicksend.py | 9 +++ apprise/plugins/custom_form.py | 126 +++++++++++++++++------------- apprise/plugins/custom_json.py | 114 +++++++++++++++------------ apprise/plugins/custom_xml.py | 118 ++++++++++++++++------------ apprise/plugins/d7networks.py | 9 +++ apprise/plugins/dapnet.py | 9 +++ apprise/plugins/dbus.py | 9 +++ apprise/plugins/dingtalk.py | 9 +++ apprise/plugins/discord.py | 9 +++ apprise/plugins/email.py | 13 +++ apprise/plugins/emby.py | 12 +++ apprise/plugins/enigma2.py | 14 ++++ apprise/plugins/fcm/__init__.py | 9 +++ apprise/plugins/feishu.py | 9 +++ apprise/plugins/flock.py | 9 +++ apprise/plugins/freemobile.py | 9 +++ apprise/plugins/gnome.py | 8 ++ apprise/plugins/google_chat.py | 12 +++ apprise/plugins/gotify.py | 14 ++++ apprise/plugins/growl.py | 11 +++ apprise/plugins/home_assistant.py | 22 +++++- apprise/plugins/httpsms.py | 9 +++ apprise/plugins/ifttt.py | 9 +++ apprise/plugins/join.py | 9 +++ apprise/plugins/kavenegar.py | 9 +++ apprise/plugins/kumulos.py | 9 +++ apprise/plugins/lametric.py | 30 +++++++ apprise/plugins/line.py | 9 +++ apprise/plugins/lunasea.py | 18 +++++ apprise/plugins/macosx.py | 8 ++ apprise/plugins/mailgun.py | 11 +++ apprise/plugins/mastodon.py | 12 +++ apprise/plugins/matrix.py | 16 ++++ apprise/plugins/mattermost.py | 16 +++- apprise/plugins/messagebird.py | 9 +++ apprise/plugins/misskey.py | 12 +++ apprise/plugins/mqtt.py | 14 ++++ apprise/plugins/msg91.py | 9 +++ apprise/plugins/msteams.py | 13 +++ apprise/plugins/nextcloud.py | 12 +++ apprise/plugins/nextcloudtalk.py | 12 +++ apprise/plugins/notica.py | 13 +++ apprise/plugins/notifiarr.py | 12 +++ apprise/plugins/notifico.py | 9 +++ apprise/plugins/ntfy.py | 20 +++++ apprise/plugins/office365.py | 12 +++ apprise/plugins/one_signal.py | 11 +++ apprise/plugins/opsgenie.py | 9 +++ apprise/plugins/pagerduty.py | 12 +++ apprise/plugins/pagertree.py | 9 +++ apprise/plugins/parseplatform.py | 13 +++ apprise/plugins/popcorn_notify.py | 9 +++ apprise/plugins/prowl.py | 9 +++ apprise/plugins/pushbullet.py | 9 +++ apprise/plugins/pushdeer.py | 12 +++ apprise/plugins/pushed.py | 9 +++ apprise/plugins/pushjet.py | 12 +++ apprise/plugins/pushme.py | 9 +++ apprise/plugins/pushover.py | 9 +++ apprise/plugins/pushsafer.py | 12 +++ apprise/plugins/pushy.py | 9 +++ apprise/plugins/reddit.py | 12 +++ apprise/plugins/revolt.py | 9 +++ apprise/plugins/rocketchat.py | 17 ++++ apprise/plugins/rsyslog.py | 9 +++ apprise/plugins/ryver.py | 9 +++ apprise/plugins/sendgrid.py | 9 +++ apprise/plugins/serverchan.py | 9 +++ apprise/plugins/ses.py | 12 +++ apprise/plugins/sfr.py | 12 +++ apprise/plugins/signal_api.py | 12 +++ apprise/plugins/simplepush.py | 9 +++ apprise/plugins/sinch.py | 12 +++ apprise/plugins/slack.py | 16 ++++ apprise/plugins/smseagle.py | 12 +++ apprise/plugins/smsmanager.py | 9 +++ apprise/plugins/smtp2go.py | 9 +++ apprise/plugins/sns.py | 12 +++ apprise/plugins/sparkpost.py | 9 +++ apprise/plugins/splunk.py | 12 +++ apprise/plugins/streamlabs.py | 9 +++ apprise/plugins/synology.py | 13 +++ apprise/plugins/syslog.py | 9 +++ apprise/plugins/techuluspush.py | 9 +++ apprise/plugins/telegram.py | 9 +++ apprise/plugins/threema.py | 9 +++ apprise/plugins/twilio.py | 12 +++ apprise/plugins/twist.py | 12 +++ apprise/plugins/twitter.py | 12 +++ apprise/plugins/voipms.py | 11 +++ apprise/plugins/vonage.py | 9 +++ apprise/plugins/webexteams.py | 9 +++ apprise/plugins/wecombot.py | 9 +++ apprise/plugins/whatsapp.py | 9 +++ apprise/plugins/windows.py | 9 +++ apprise/plugins/xbmc.py | 19 +++++ apprise/plugins/zulip.py | 12 +++ apprise/url.py | 5 ++ test/helpers/rest.py | 14 ++++ test/test_api.py | 51 +++++++++--- test/test_plugin_aprs.py | 3 + 109 files changed, 1381 insertions(+), 174 deletions(-) diff --git a/apprise/cli.py b/apprise/cli.py index 20aceed34a..3316b48e7b 100644 --- a/apprise/cli.py +++ b/apprise/cli.py @@ -123,7 +123,7 @@ # Global Support # - # C:\ProgramData\Apprise\ + # C:\ProgramData\Apprise '%ALLUSERSPROFILE%\\Apprise\\apprise', '%ALLUSERSPROFILE%\\Apprise\\apprise.conf', '%ALLUSERSPROFILE%\\Apprise\\apprise.yml', diff --git a/apprise/plugins/aprs.py b/apprise/plugins/aprs.py index b8adef5aa6..d87025feec 100644 --- a/apprise/plugins/aprs.py +++ b/apprise/plugins/aprs.py @@ -729,6 +729,15 @@ def url(self, privacy=False, *args, **kwargs): params=NotifyAprs.urlencode(params), ) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.user, self.password, self.locale) + def __len__(self): """ Returns the number of targets associated with this notification diff --git a/apprise/plugins/bark.py b/apprise/plugins/bark.py index e2f5bbfb4a..e676e0c31d 100644 --- a/apprise/plugins/bark.py +++ b/apprise/plugins/bark.py @@ -395,6 +395,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, self.port, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/boxcar.py b/apprise/plugins/boxcar.py index 851cdd3d8b..f7f16b04ac 100644 --- a/apprise/plugins/boxcar.py +++ b/apprise/plugins/boxcar.py @@ -341,6 +341,15 @@ def url(self, privacy=False, *args, **kwargs): params=NotifyBoxcar.urlencode(params), ) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.access, self.secret) + def __len__(self): """ Returns the number of targets associated with this notification diff --git a/apprise/plugins/bulksms.py b/apprise/plugins/bulksms.py index 9bbbefe59c..f53f612676 100644 --- a/apprise/plugins/bulksms.py +++ b/apprise/plugins/bulksms.py @@ -413,6 +413,19 @@ def url(self, privacy=False, *args, **kwargs): for x in self.groups])), params=NotifyBulkSMS.urlencode(params)) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, + self.user if self.user else None, + self.password if self.password else None, + ) + def __len__(self): """ Returns the number of targets associated with this notification diff --git a/apprise/plugins/bulkvs.py b/apprise/plugins/bulkvs.py index 53a3630083..a02d8ab8c5 100644 --- a/apprise/plugins/bulkvs.py +++ b/apprise/plugins/bulkvs.py @@ -304,6 +304,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.source, self.user, self.password) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/burstsms.py b/apprise/plugins/burstsms.py index eb19df8e4c..3b6f2669a6 100644 --- a/apprise/plugins/burstsms.py +++ b/apprise/plugins/burstsms.py @@ -378,6 +378,15 @@ def url(self, privacy=False, *args, **kwargs): [NotifyBurstSMS.quote(x, safe='') for x in self.targets]), params=NotifyBurstSMS.urlencode(params)) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.apikey, self.secret, self.source) + def __len__(self): """ Returns the number of targets associated with this notification diff --git a/apprise/plugins/chantify.py b/apprise/plugins/chantify.py index d549a59fa1..e7c5f63e97 100644 --- a/apprise/plugins/chantify.py +++ b/apprise/plugins/chantify.py @@ -181,6 +181,15 @@ def url(self, privacy=False, *args, **kwargs): params=NotifyChantify.urlencode(params), ) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.token) + @staticmethod def parse_url(url): """ diff --git a/apprise/plugins/clicksend.py b/apprise/plugins/clicksend.py index 9ade1055e1..7f28ac9135 100644 --- a/apprise/plugins/clicksend.py +++ b/apprise/plugins/clicksend.py @@ -285,6 +285,15 @@ def url(self, privacy=False, *args, **kwargs): params=NotifyClickSend.urlencode(params), ) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.user, self.password) + def __len__(self): """ Returns the number of targets associated with this notification diff --git a/apprise/plugins/custom_form.py b/apprise/plugins/custom_form.py index 0f36643f75..05fe51d1f1 100644 --- a/apprise/plugins/custom_form.py +++ b/apprise/plugins/custom_form.py @@ -272,62 +272,6 @@ def __init__(self, headers=None, method=None, payload=None, params=None, return - def url(self, privacy=False, *args, **kwargs): - """ - Returns the URL built dynamically based on specified arguments. - """ - - # Define any URL parameters - params = { - 'method': self.method, - } - - # Extend our parameters - params.update(self.url_parameters(privacy=privacy, *args, **kwargs)) - - # Append our headers into our parameters - params.update({'+{}'.format(k): v for k, v in self.headers.items()}) - - # Append our GET params into our parameters - params.update({'-{}'.format(k): v for k, v in self.params.items()}) - - # Append our payload extra's into our parameters - params.update( - {':{}'.format(k): v for k, v in self.payload_extras.items()}) - params.update( - {':{}'.format(k): v for k, v in self.payload_overrides.items()}) - - if self.attach_as != self.attach_as_default: - # Provide Attach-As extension details - params['attach-as'] = self.attach_as - - # Determine Authentication - auth = '' - if self.user and self.password: - auth = '{user}:{password}@'.format( - user=NotifyForm.quote(self.user, safe=''), - password=self.pprint( - self.password, privacy, mode=PrivacyMode.Secret, safe=''), - ) - elif self.user: - auth = '{user}@'.format( - user=NotifyForm.quote(self.user, safe=''), - ) - - default_port = 443 if self.secure else 80 - - return '{schema}://{auth}{hostname}{port}{fullpath}?{params}'.format( - schema=self.secure_protocol if self.secure else self.protocol, - auth=auth, - # never encode hostname since we're expecting it to be a valid one - hostname=self.host, - port='' if self.port is None or self.port == default_port - else ':{}'.format(self.port), - fullpath=NotifyForm.quote(self.fullpath, safe='/') - if self.fullpath else '/', - params=NotifyForm.urlencode(params), - ) - def send(self, body, title='', notify_type=NotifyType.INFO, attach=None, **kwargs): """ @@ -486,6 +430,76 @@ def send(self, body, title='', notify_type=NotifyType.INFO, attach=None, return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, + self.port if self.port else (443 if self.secure else 80), + self.fullpath.rstrip('/'), + ) + + def url(self, privacy=False, *args, **kwargs): + """ + Returns the URL built dynamically based on specified arguments. + """ + + # Define any URL parameters + params = { + 'method': self.method, + } + + # Extend our parameters + params.update(self.url_parameters(privacy=privacy, *args, **kwargs)) + + # Append our headers into our parameters + params.update({'+{}'.format(k): v for k, v in self.headers.items()}) + + # Append our GET params into our parameters + params.update({'-{}'.format(k): v for k, v in self.params.items()}) + + # Append our payload extra's into our parameters + params.update( + {':{}'.format(k): v for k, v in self.payload_extras.items()}) + params.update( + {':{}'.format(k): v for k, v in self.payload_overrides.items()}) + + if self.attach_as != self.attach_as_default: + # Provide Attach-As extension details + params['attach-as'] = self.attach_as + + # Determine Authentication + auth = '' + if self.user and self.password: + auth = '{user}:{password}@'.format( + user=NotifyForm.quote(self.user, safe=''), + password=self.pprint( + self.password, privacy, mode=PrivacyMode.Secret, safe=''), + ) + elif self.user: + auth = '{user}@'.format( + user=NotifyForm.quote(self.user, safe=''), + ) + + default_port = 443 if self.secure else 80 + + return '{schema}://{auth}{hostname}{port}{fullpath}?{params}'.format( + schema=self.secure_protocol if self.secure else self.protocol, + auth=auth, + # never encode hostname since we're expecting it to be a valid one + hostname=self.host, + port='' if self.port is None or self.port == default_port + else ':{}'.format(self.port), + fullpath=NotifyForm.quote(self.fullpath, safe='/') + if self.fullpath else '/', + params=NotifyForm.urlencode(params), + ) + @staticmethod def parse_url(url): """ diff --git a/apprise/plugins/custom_json.py b/apprise/plugins/custom_json.py index e0d7a67538..25b4467d8f 100644 --- a/apprise/plugins/custom_json.py +++ b/apprise/plugins/custom_json.py @@ -195,56 +195,6 @@ def __init__(self, headers=None, method=None, payload=None, params=None, return - def url(self, privacy=False, *args, **kwargs): - """ - Returns the URL built dynamically based on specified arguments. - """ - - # Define any URL parameters - params = { - 'method': self.method, - } - - # Extend our parameters - params.update(self.url_parameters(privacy=privacy, *args, **kwargs)) - - # Append our headers into our parameters - params.update({'+{}'.format(k): v for k, v in self.headers.items()}) - - # Append our GET params into our parameters - params.update({'-{}'.format(k): v for k, v in self.params.items()}) - - # Append our payload extra's into our parameters - params.update( - {':{}'.format(k): v for k, v in self.payload_extras.items()}) - - # Determine Authentication - auth = '' - if self.user and self.password: - auth = '{user}:{password}@'.format( - user=NotifyJSON.quote(self.user, safe=''), - password=self.pprint( - self.password, privacy, mode=PrivacyMode.Secret, safe=''), - ) - elif self.user: - auth = '{user}@'.format( - user=NotifyJSON.quote(self.user, safe=''), - ) - - default_port = 443 if self.secure else 80 - - return '{schema}://{auth}{hostname}{port}{fullpath}?{params}'.format( - schema=self.secure_protocol if self.secure else self.protocol, - auth=auth, - # never encode hostname since we're expecting it to be a valid one - hostname=self.host, - port='' if self.port is None or self.port == default_port - else ':{}'.format(self.port), - fullpath=NotifyJSON.quote(self.fullpath, safe='/') - if self.fullpath else '/', - params=NotifyJSON.urlencode(params), - ) - def send(self, body, title='', notify_type=NotifyType.INFO, attach=None, **kwargs): """ @@ -395,6 +345,70 @@ def send(self, body, title='', notify_type=NotifyType.INFO, attach=None, return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, + self.port if self.port else (443 if self.secure else 80), + self.fullpath.rstrip('/'), + ) + + def url(self, privacy=False, *args, **kwargs): + """ + Returns the URL built dynamically based on specified arguments. + """ + + # Define any URL parameters + params = { + 'method': self.method, + } + + # Extend our parameters + params.update(self.url_parameters(privacy=privacy, *args, **kwargs)) + + # Append our headers into our parameters + params.update({'+{}'.format(k): v for k, v in self.headers.items()}) + + # Append our GET params into our parameters + params.update({'-{}'.format(k): v for k, v in self.params.items()}) + + # Append our payload extra's into our parameters + params.update( + {':{}'.format(k): v for k, v in self.payload_extras.items()}) + + # Determine Authentication + auth = '' + if self.user and self.password: + auth = '{user}:{password}@'.format( + user=NotifyJSON.quote(self.user, safe=''), + password=self.pprint( + self.password, privacy, mode=PrivacyMode.Secret, safe=''), + ) + elif self.user: + auth = '{user}@'.format( + user=NotifyJSON.quote(self.user, safe=''), + ) + + default_port = 443 if self.secure else 80 + + return '{schema}://{auth}{hostname}{port}{fullpath}?{params}'.format( + schema=self.secure_protocol if self.secure else self.protocol, + auth=auth, + # never encode hostname since we're expecting it to be a valid one + hostname=self.host, + port='' if self.port is None or self.port == default_port + else ':{}'.format(self.port), + fullpath=NotifyJSON.quote(self.fullpath, safe='/') + if self.fullpath else '/', + params=NotifyJSON.urlencode(params), + ) + @staticmethod def parse_url(url): """ diff --git a/apprise/plugins/custom_xml.py b/apprise/plugins/custom_xml.py index b7928fceb9..f72e9a1aaf 100644 --- a/apprise/plugins/custom_xml.py +++ b/apprise/plugins/custom_xml.py @@ -242,58 +242,6 @@ def __init__(self, headers=None, method=None, payload=None, params=None, return - def url(self, privacy=False, *args, **kwargs): - """ - Returns the URL built dynamically based on specified arguments. - """ - - # Define any URL parameters - params = { - 'method': self.method, - } - - # Extend our parameters - params.update(self.url_parameters(privacy=privacy, *args, **kwargs)) - - # Append our headers into our parameters - params.update({'+{}'.format(k): v for k, v in self.headers.items()}) - - # Append our GET params into our parameters - params.update({'-{}'.format(k): v for k, v in self.params.items()}) - - # Append our payload extra's into our parameters - params.update( - {':{}'.format(k): v for k, v in self.payload_extras.items()}) - params.update( - {':{}'.format(k): v for k, v in self.payload_overrides.items()}) - - # Determine Authentication - auth = '' - if self.user and self.password: - auth = '{user}:{password}@'.format( - user=NotifyXML.quote(self.user, safe=''), - password=self.pprint( - self.password, privacy, mode=PrivacyMode.Secret, safe=''), - ) - elif self.user: - auth = '{user}@'.format( - user=NotifyXML.quote(self.user, safe=''), - ) - - default_port = 443 if self.secure else 80 - - return '{schema}://{auth}{hostname}{port}{fullpath}?{params}'.format( - schema=self.secure_protocol if self.secure else self.protocol, - auth=auth, - # never encode hostname since we're expecting it to be a valid one - hostname=self.host, - port='' if self.port is None or self.port == default_port - else ':{}'.format(self.port), - fullpath=NotifyXML.quote(self.fullpath, safe='/') - if self.fullpath else '/', - params=NotifyXML.urlencode(params), - ) - def send(self, body, title='', notify_type=NotifyType.INFO, attach=None, **kwargs): """ @@ -467,6 +415,72 @@ def send(self, body, title='', notify_type=NotifyType.INFO, attach=None, return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, + self.port if self.port else (443 if self.secure else 80), + self.fullpath.rstrip('/'), + ) + + def url(self, privacy=False, *args, **kwargs): + """ + Returns the URL built dynamically based on specified arguments. + """ + + # Define any URL parameters + params = { + 'method': self.method, + } + + # Extend our parameters + params.update(self.url_parameters(privacy=privacy, *args, **kwargs)) + + # Append our headers into our parameters + params.update({'+{}'.format(k): v for k, v in self.headers.items()}) + + # Append our GET params into our parameters + params.update({'-{}'.format(k): v for k, v in self.params.items()}) + + # Append our payload extra's into our parameters + params.update( + {':{}'.format(k): v for k, v in self.payload_extras.items()}) + params.update( + {':{}'.format(k): v for k, v in self.payload_overrides.items()}) + + # Determine Authentication + auth = '' + if self.user and self.password: + auth = '{user}:{password}@'.format( + user=NotifyXML.quote(self.user, safe=''), + password=self.pprint( + self.password, privacy, mode=PrivacyMode.Secret, safe=''), + ) + elif self.user: + auth = '{user}@'.format( + user=NotifyXML.quote(self.user, safe=''), + ) + + default_port = 443 if self.secure else 80 + + return '{schema}://{auth}{hostname}{port}{fullpath}?{params}'.format( + schema=self.secure_protocol if self.secure else self.protocol, + auth=auth, + # never encode hostname since we're expecting it to be a valid one + hostname=self.host, + port='' if self.port is None or self.port == default_port + else ':{}'.format(self.port), + fullpath=NotifyXML.quote(self.fullpath, safe='/') + if self.fullpath else '/', + params=NotifyXML.urlencode(params), + ) + @staticmethod def parse_url(url): """ diff --git a/apprise/plugins/d7networks.py b/apprise/plugins/d7networks.py index ad55e21973..ff2e31b055 100644 --- a/apprise/plugins/d7networks.py +++ b/apprise/plugins/d7networks.py @@ -354,6 +354,15 @@ def url(self, privacy=False, *args, **kwargs): [NotifyD7Networks.quote(x, safe='') for x in self.targets]), params=NotifyD7Networks.urlencode(params)) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.token) + def __len__(self): """ Returns the number of targets associated with this notification diff --git a/apprise/plugins/dapnet.py b/apprise/plugins/dapnet.py index 60a18acd4f..725174c14d 100644 --- a/apprise/plugins/dapnet.py +++ b/apprise/plugins/dapnet.py @@ -346,6 +346,15 @@ def url(self, privacy=False, *args, **kwargs): params=NotifyDapnet.urlencode(params), ) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.user, self.password) + def __len__(self): """ Returns the number of targets associated with this notification diff --git a/apprise/plugins/dbus.py b/apprise/plugins/dbus.py index f2361fd623..19de7484d0 100644 --- a/apprise/plugins/dbus.py +++ b/apprise/plugins/dbus.py @@ -412,6 +412,15 @@ def url(self, privacy=False, *args, **kwargs): params=NotifyDBus.urlencode(params), ) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return self.schema + @staticmethod def parse_url(url): """ diff --git a/apprise/plugins/dingtalk.py b/apprise/plugins/dingtalk.py index 2ca1bc55ba..e675f5302f 100644 --- a/apprise/plugins/dingtalk.py +++ b/apprise/plugins/dingtalk.py @@ -310,6 +310,15 @@ def url(self, privacy=False, *args, **kwargs): [NotifyDingTalk.quote(x, safe='') for x in self.targets]), args=NotifyDingTalk.urlencode(args)) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.secret, self.token) + def __len__(self): """ Returns the number of targets associated with this notification diff --git a/apprise/plugins/discord.py b/apprise/plugins/discord.py index 14c6152ba1..e41e22cdc3 100644 --- a/apprise/plugins/discord.py +++ b/apprise/plugins/discord.py @@ -607,6 +607,15 @@ def url(self, privacy=False, *args, **kwargs): params=NotifyDiscord.urlencode(params), ) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.webhook_id, self.webhook_token) + @staticmethod def parse_url(url): """ diff --git a/apprise/plugins/email.py b/apprise/plugins/email.py index 142c93cfbd..a8989d4ff6 100644 --- a/apprise/plugins/email.py +++ b/apprise/plugins/email.py @@ -1031,6 +1031,19 @@ def url(self, privacy=False, *args, **kwargs): params=NotifyEmail.urlencode(params), ) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, self.port, + self.from_addr, + ) + def __len__(self): """ Returns the number of targets associated with this notification diff --git a/apprise/plugins/emby.py b/apprise/plugins/emby.py index 5e4e0b89fd..5824932e86 100644 --- a/apprise/plugins/emby.py +++ b/apprise/plugins/emby.py @@ -593,6 +593,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, self.user, self.password, self.host, + self.port if self.port else (443 if self.secure else 80), + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/enigma2.py b/apprise/plugins/enigma2.py index 8b1fff6874..a79d3b57e1 100644 --- a/apprise/plugins/enigma2.py +++ b/apprise/plugins/enigma2.py @@ -181,6 +181,20 @@ def __init__(self, timeout=None, headers=None, **kwargs): return + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, + self.user, self.password, self.host, + self.port if self.port else (443 if self.secure else 80), + self.fullpath.rstrip('/'), + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/fcm/__init__.py b/apprise/plugins/fcm/__init__.py index 9dc0679f17..e5db817e2b 100644 --- a/apprise/plugins/fcm/__init__.py +++ b/apprise/plugins/fcm/__init__.py @@ -507,6 +507,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.mode, self.apikey, self.project) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/feishu.py b/apprise/plugins/feishu.py index 961523baba..9b3c74ea4e 100644 --- a/apprise/plugins/feishu.py +++ b/apprise/plugins/feishu.py @@ -192,6 +192,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.token) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/flock.py b/apprise/plugins/flock.py index bf2cd131d2..99ce3582ba 100644 --- a/apprise/plugins/flock.py +++ b/apprise/plugins/flock.py @@ -308,6 +308,15 @@ def _post(self, url, headers, payload): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.token) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/freemobile.py b/apprise/plugins/freemobile.py index 4ff3d48221..5208d5664d 100644 --- a/apprise/plugins/freemobile.py +++ b/apprise/plugins/freemobile.py @@ -103,6 +103,15 @@ def __init__(self, **kwargs): return + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.user, self.password) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/gnome.py b/apprise/plugins/gnome.py index b64b51304f..4d2ec22d45 100644 --- a/apprise/plugins/gnome.py +++ b/apprise/plugins/gnome.py @@ -224,6 +224,14 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return self.protocol + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/google_chat.py b/apprise/plugins/google_chat.py index f30cdae490..f12e24029e 100644 --- a/apprise/plugins/google_chat.py +++ b/apprise/plugins/google_chat.py @@ -265,6 +265,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, self.workspace, self.webhook_key, + self.webhook_token, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/gotify.py b/apprise/plugins/gotify.py index bf6c1b281d..1be2d00527 100644 --- a/apprise/plugins/gotify.py +++ b/apprise/plugins/gotify.py @@ -265,6 +265,20 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, + self.port if self.port else (443 if self.secure else 80), + self.fullpath.rstrip('/'), + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/growl.py b/apprise/plugins/growl.py index 0b36721886..2f0c37146a 100644 --- a/apprise/plugins/growl.py +++ b/apprise/plugins/growl.py @@ -338,6 +338,17 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, self.port, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/home_assistant.py b/apprise/plugins/home_assistant.py index b0ffcaa648..c59b58a9a0 100644 --- a/apprise/plugins/home_assistant.py +++ b/apprise/plugins/home_assistant.py @@ -179,8 +179,8 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): if isinstance(self.port, int): url += ':%d' % self.port - url += '' if not self.fullpath else '/' + self.fullpath.strip('/') - url += '/api/services/persistent_notification/create' + url += self.fullpath.rstrip('/') + \ + '/api/services/persistent_notification/create' self.logger.debug('Home Assistant POST URL: %s (cert_verify=%r)' % ( url, self.verify_certificate, @@ -231,6 +231,22 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, + self.port if self.port else ( + 443 if self.secure else self.default_insecure_port), + self.fullpath.rstrip('/'), + self.accesstoken, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. @@ -302,7 +318,7 @@ def parse_url(url): results['accesstoken'] = fullpath.pop() if fullpath else None # Re-assemble our full path - results['fullpath'] = '/'.join(fullpath) + results['fullpath'] = '/' + '/'.join(fullpath) if fullpath else '' # Allow the specification of a unique notification_id so that # it will always replace the last one sent. diff --git a/apprise/plugins/httpsms.py b/apprise/plugins/httpsms.py index b36e286d71..b4da6c627c 100644 --- a/apprise/plugins/httpsms.py +++ b/apprise/plugins/httpsms.py @@ -253,6 +253,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.source, self.apikey) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/ifttt.py b/apprise/plugins/ifttt.py index 9d89b14642..64d9cc31b2 100644 --- a/apprise/plugins/ifttt.py +++ b/apprise/plugins/ifttt.py @@ -287,6 +287,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.webhook_id) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/join.py b/apprise/plugins/join.py index b92bb37a3a..239f9682f0 100644 --- a/apprise/plugins/join.py +++ b/apprise/plugins/join.py @@ -345,6 +345,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.apikey) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/kavenegar.py b/apprise/plugins/kavenegar.py index e4963f4095..ea3bd8ed32 100644 --- a/apprise/plugins/kavenegar.py +++ b/apprise/plugins/kavenegar.py @@ -304,6 +304,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.source, self.apikey) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/kumulos.py b/apprise/plugins/kumulos.py index 504dcc379f..941f163db4 100644 --- a/apprise/plugins/kumulos.py +++ b/apprise/plugins/kumulos.py @@ -198,6 +198,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return False return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.apikey, self.serverkey) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/lametric.py b/apprise/plugins/lametric.py index 7fdd8ebc91..b6124a91f0 100644 --- a/apprise/plugins/lametric.py +++ b/apprise/plugins/lametric.py @@ -783,6 +783,29 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + if self.mode == LametricMode.DEVICE: + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.lametric_apikey, self.host, + self.port if self.port else ( + 443 if self.secure else + self.template_tokens['port']['default']), + ) + + return ( + self.protocol, + self.lametric_app_access_token, + self.lametric_app_id, + self.lametric_app_ver, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. @@ -871,6 +894,9 @@ def parse_url(url): results['password'] = results['user'] results['user'] = None + # Get unquoted entries + entries = NotifyLametric.split_path(results['fullpath']) + # Priority Handling if 'priority' in results['qsd'] and results['qsd']['priority']: results['priority'] = NotifyLametric.unquote( @@ -913,6 +939,10 @@ def parse_url(url): results['app_ver'] = \ NotifyLametric.unquote(results['qsd']['app_ver']) + elif entries: + # Store our app id + results['app_ver'] = entries.pop(0) + if 'token' in results['qsd'] and results['qsd']['token']: # Extract Application Access Token from an argument results['app_token'] = \ diff --git a/apprise/plugins/line.py b/apprise/plugins/line.py index 07a01e769b..c177e26f8c 100644 --- a/apprise/plugins/line.py +++ b/apprise/plugins/line.py @@ -241,6 +241,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.token) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/lunasea.py b/apprise/plugins/lunasea.py index 2af5191793..97291fc9e8 100644 --- a/apprise/plugins/lunasea.py +++ b/apprise/plugins/lunasea.py @@ -324,6 +324,24 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + secure = self.secure_protocol[0] \ + if self.mode == LunaSeaMode.CLOUD else ( + self.secure_protocol[0] if self.secure else self.protocol[0]) + return ( + secure, + self.host if self.mode == LunaSeaMode.PRIVATE else None, + self.port if self.port else (443 if self.secure else 80), + self.user if self.user else None, + self.password if self.password else None, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/macosx.py b/apprise/plugins/macosx.py index 31b7101bd4..f39fa764a8 100644 --- a/apprise/plugins/macosx.py +++ b/apprise/plugins/macosx.py @@ -203,6 +203,14 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): self.logger.info('Sent MacOSX notification.') return True + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return self.protocol + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/mailgun.py b/apprise/plugins/mailgun.py index 69ab72ddaa..4b73957ad2 100644 --- a/apprise/plugins/mailgun.py +++ b/apprise/plugins/mailgun.py @@ -579,6 +579,17 @@ def send(self, body, title='', notify_type=NotifyType.INFO, attach=None, return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, self.host, self.apikey, self.region_name, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/mastodon.py b/apprise/plugins/mastodon.py index b6e451ad11..85379ba0ae 100644 --- a/apprise/plugins/mastodon.py +++ b/apprise/plugins/mastodon.py @@ -336,6 +336,18 @@ def __init__(self, token=None, targets=None, batch=True, return + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol[0], self.token, self.host, + self.port if self.port else (443 if self.secure else 80), + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/matrix.py b/apprise/plugins/matrix.py index 70a40987f4..8f07828e09 100644 --- a/apprise/plugins/matrix.py +++ b/apprise/plugins/matrix.py @@ -1336,6 +1336,22 @@ def __del__(self): # the end user if we don't have to. pass + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.host if self.mode != MatrixWebhookMode.T2BOT + else self.access_token, + self.port if self.port else (443 if self.secure else 80), + self.user if self.mode != MatrixWebhookMode.T2BOT else None, + self.password if self.mode != MatrixWebhookMode.T2BOT else None, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/mattermost.py b/apprise/plugins/mattermost.py index 481a9b8520..3dcc4ad020 100644 --- a/apprise/plugins/mattermost.py +++ b/apprise/plugins/mattermost.py @@ -220,8 +220,8 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): payload['channel'] = channel url = '{}://{}:{}{}/hooks/{}'.format( - self.schema, self.host, self.port, self.fullpath, - self.token) + self.schema, self.host, self.port, + self.fullpath.rstrip('/'), self.token) self.logger.debug('Mattermost POST URL: %s (cert_verify=%r)' % ( url, self.verify_certificate, @@ -283,6 +283,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): # Return our overall status return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.token, self.host, self.port, self.fullpath, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/messagebird.py b/apprise/plugins/messagebird.py index c496d347e3..053c593031 100644 --- a/apprise/plugins/messagebird.py +++ b/apprise/plugins/messagebird.py @@ -291,6 +291,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.apikey, self.source) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/misskey.py b/apprise/plugins/misskey.py index 73b8f7c6eb..21d0250dff 100644 --- a/apprise/plugins/misskey.py +++ b/apprise/plugins/misskey.py @@ -191,6 +191,18 @@ def __init__(self, token=None, visibility=None, **kwargs): return + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.token, self.host, self.port, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/mqtt.py b/apprise/plugins/mqtt.py index 1e09cd147e..83fe84d6a3 100644 --- a/apprise/plugins/mqtt.py +++ b/apprise/plugins/mqtt.py @@ -429,6 +429,20 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, self.port, + self.fullpath.rstrip('/'), + self.client_id, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/msg91.py b/apprise/plugins/msg91.py index 28a5bf1836..cf5fea9b64 100644 --- a/apprise/plugins/msg91.py +++ b/apprise/plugins/msg91.py @@ -310,6 +310,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.template, self.authkey) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/msteams.py b/apprise/plugins/msteams.py index 2e0957f32a..7400de9761 100644 --- a/apprise/plugins/msteams.py +++ b/apprise/plugins/msteams.py @@ -463,6 +463,19 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, + self.team if self.version > 1 else None, + self.token_a, self.token_b, self.token_c, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/nextcloud.py b/apprise/plugins/nextcloud.py index 9acfc43d58..7afe2d9af0 100644 --- a/apprise/plugins/nextcloud.py +++ b/apprise/plugins/nextcloud.py @@ -278,6 +278,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, self.port, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/nextcloudtalk.py b/apprise/plugins/nextcloudtalk.py index b1b0147706..7ba953c3dc 100644 --- a/apprise/plugins/nextcloudtalk.py +++ b/apprise/plugins/nextcloudtalk.py @@ -253,6 +253,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, self.port, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/notica.py b/apprise/plugins/notica.py index 661fde1d10..9c5778af2b 100644 --- a/apprise/plugins/notica.py +++ b/apprise/plugins/notica.py @@ -278,6 +278,19 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.mode, self.token, self.user, self.password, self.host, + self.port, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/notifiarr.py b/apprise/plugins/notifiarr.py index cc13e1a56a..535ba96260 100644 --- a/apprise/plugins/notifiarr.py +++ b/apprise/plugins/notifiarr.py @@ -231,6 +231,18 @@ def __init__(self, apikey=None, include_image=None, return + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.apikey, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/notifico.py b/apprise/plugins/notifico.py index 5cb0d666e9..db88bf6b2e 100644 --- a/apprise/plugins/notifico.py +++ b/apprise/plugins/notifico.py @@ -197,6 +197,15 @@ def __init__(self, project_id, msghook, color=True, prefix=True, ) return + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.project_id, self.msghook) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/ntfy.py b/apprise/plugins/ntfy.py index 4814c9aa5c..b30d53619c 100644 --- a/apprise/plugins/ntfy.py +++ b/apprise/plugins/ntfy.py @@ -656,6 +656,26 @@ def _send(self, topic, body=None, title=None, attach=None, image_url=None, return False, response + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + + kwargs = [ + self.secure_protocol if self.secure else self.protocol, + self.host, + self.port if self.port else (443 if self.secure else 80), + ] + + if self.auth == NtfyAuth.BASIC: + kwargs.extend([self.user, self.password]) + + elif self.token: # NtfyAuth.TOKEN also + kwargs.append(self.token) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/office365.py b/apprise/plugins/office365.py index b04f7a037f..21a1d6fa09 100644 --- a/apprise/plugins/office365.py +++ b/apprise/plugins/office365.py @@ -558,6 +558,18 @@ def _fetch(self, url, payload, return (True, content) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, self.email, self.tenant, self.client_id, + self.secret, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/one_signal.py b/apprise/plugins/one_signal.py index 76ec212f4e..a2457bd372 100644 --- a/apprise/plugins/one_signal.py +++ b/apprise/plugins/one_signal.py @@ -392,6 +392,17 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, self.template_id, self.app, self.apikey, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/opsgenie.py b/apprise/plugins/opsgenie.py index 5327ec803f..38c3b94bd8 100644 --- a/apprise/plugins/opsgenie.py +++ b/apprise/plugins/opsgenie.py @@ -476,6 +476,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.region_name, self.apikey) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/pagerduty.py b/apprise/plugins/pagerduty.py index c9d5555278..51bd38887c 100644 --- a/apprise/plugins/pagerduty.py +++ b/apprise/plugins/pagerduty.py @@ -412,6 +412,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, self.integration_key, self.apikey, + self.source, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/pagertree.py b/apprise/plugins/pagertree.py index 8a041a358d..7d82f677ce 100644 --- a/apprise/plugins/pagertree.py +++ b/apprise/plugins/pagertree.py @@ -299,6 +299,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.integration) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/parseplatform.py b/apprise/plugins/parseplatform.py index cd59d05750..808c3099cf 100644 --- a/apprise/plugins/parseplatform.py +++ b/apprise/plugins/parseplatform.py @@ -257,6 +257,19 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.application_id, self.master_key, self.host, self.port, + self.fullpath, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/popcorn_notify.py b/apprise/plugins/popcorn_notify.py index 388aa2199c..16d34ab092 100644 --- a/apprise/plugins/popcorn_notify.py +++ b/apprise/plugins/popcorn_notify.py @@ -242,6 +242,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.apikey) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/prowl.py b/apprise/plugins/prowl.py index c174615c0c..55c4c6be2c 100644 --- a/apprise/plugins/prowl.py +++ b/apprise/plugins/prowl.py @@ -250,6 +250,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.apikey, self.providerkey) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/pushbullet.py b/apprise/plugins/pushbullet.py index 8e006db1db..9f2226f352 100644 --- a/apprise/plugins/pushbullet.py +++ b/apprise/plugins/pushbullet.py @@ -386,6 +386,15 @@ def _send(self, url, payload, **kwargs): if files: files['file'][1].close() + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.accesstoken) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/pushdeer.py b/apprise/plugins/pushdeer.py index fa888b1590..226e3f2103 100644 --- a/apprise/plugins/pushdeer.py +++ b/apprise/plugins/pushdeer.py @@ -180,6 +180,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.push_key, self.host, self.port, + ) + def url(self, privacy=False): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/pushed.py b/apprise/plugins/pushed.py index 1ed83b9e45..c0727ad15e 100644 --- a/apprise/plugins/pushed.py +++ b/apprise/plugins/pushed.py @@ -303,6 +303,15 @@ def _send(self, payload, notify_type, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.app_key, self.app_secret) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/pushjet.py b/apprise/plugins/pushjet.py index f8dcfdf318..bc368b109f 100644 --- a/apprise/plugins/pushjet.py +++ b/apprise/plugins/pushjet.py @@ -117,6 +117,18 @@ def __init__(self, secret_key, **kwargs): return + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, self.port, self.secret_key, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/pushme.py b/apprise/plugins/pushme.py index abbed7944f..54d4032de6 100644 --- a/apprise/plugins/pushme.py +++ b/apprise/plugins/pushme.py @@ -171,6 +171,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.token) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/pushover.py b/apprise/plugins/pushover.py index 954e7dd0fe..07881884ab 100644 --- a/apprise/plugins/pushover.py +++ b/apprise/plugins/pushover.py @@ -549,6 +549,15 @@ def _send(self, payload, attach=None): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.user_key, self.token) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/pushsafer.py b/apprise/plugins/pushsafer.py index 7bdca7a692..7d4052c0a2 100644 --- a/apprise/plugins/pushsafer.py +++ b/apprise/plugins/pushsafer.py @@ -756,6 +756,18 @@ def _send(self, payload, **kwargs): return False, response + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.privatekey, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/pushy.py b/apprise/plugins/pushy.py index bb2a24ecd3..d0995df3be 100644 --- a/apprise/plugins/pushy.py +++ b/apprise/plugins/pushy.py @@ -310,6 +310,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.apikey) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/reddit.py b/apprise/plugins/reddit.py index 3a60b5e03b..1c261be9c8 100644 --- a/apprise/plugins/reddit.py +++ b/apprise/plugins/reddit.py @@ -324,6 +324,18 @@ def __init__(self, app_id=None, app_secret=None, targets=None, return + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, self.client_id, self.client_secret, + self.user, self.password, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/revolt.py b/apprise/plugins/revolt.py index 1f518540bb..2edbed3305 100644 --- a/apprise/plugins/revolt.py +++ b/apprise/plugins/revolt.py @@ -354,6 +354,15 @@ def _send(self, payload, channel_id, retries=1, **kwargs): return (True, content) + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.bot_token) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/rocketchat.py b/apprise/plugins/rocketchat.py index 973651e30e..7850c3d059 100644 --- a/apprise/plugins/rocketchat.py +++ b/apprise/plugins/rocketchat.py @@ -319,6 +319,23 @@ def __init__(self, webhook=None, targets=None, mode=None, avatar=None, return + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.host, + self.port if self.port else (443 if self.secure else 80), + self.user, + self.password if self.mode in ( + RocketChatAuthMode.BASIC, RocketChatAuthMode.TOKEN) + else self.webhook, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/rsyslog.py b/apprise/plugins/rsyslog.py index 9631c72fd2..e5efb62775 100644 --- a/apprise/plugins/rsyslog.py +++ b/apprise/plugins/rsyslog.py @@ -300,6 +300,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.protocol, self.host, self.port) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/ryver.py b/apprise/plugins/ryver.py index 114dc6a0c9..c792c3d782 100644 --- a/apprise/plugins/ryver.py +++ b/apprise/plugins/ryver.py @@ -272,6 +272,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.organization, self.token) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/sendgrid.py b/apprise/plugins/sendgrid.py index d50839f177..56a99a5715 100644 --- a/apprise/plugins/sendgrid.py +++ b/apprise/plugins/sendgrid.py @@ -243,6 +243,15 @@ def __init__(self, apikey, from_email, targets=None, cc=None, return + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.apikey, self.from_email) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/serverchan.py b/apprise/plugins/serverchan.py index 667d2e9511..db1571417f 100644 --- a/apprise/plugins/serverchan.py +++ b/apprise/plugins/serverchan.py @@ -149,6 +149,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.token) + def url(self, privacy=False): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/ses.py b/apprise/plugins/ses.py index 5a2c047a7b..5fe4a3697b 100644 --- a/apprise/plugins/ses.py +++ b/apprise/plugins/ses.py @@ -770,6 +770,18 @@ def _xml_iter(root, response): return response + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, self.from_addr, self.aws_access_key_id, + self.aws_secret_access_key, self.aws_region_name, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/sfr.py b/apprise/plugins/sfr.py index c41e07525b..27ea0fb0b3 100644 --- a/apprise/plugins/sfr.py +++ b/apprise/plugins/sfr.py @@ -356,6 +356,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.space_id, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/signal_api.py b/apprise/plugins/signal_api.py index 7e557133ce..5795e0cfe5 100644 --- a/apprise/plugins/signal_api.py +++ b/apprise/plugins/signal_api.py @@ -372,6 +372,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, attach=None, return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, self.port, self.source, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/simplepush.py b/apprise/plugins/simplepush.py index 10b01b0f81..023fcf9d53 100644 --- a/apprise/plugins/simplepush.py +++ b/apprise/plugins/simplepush.py @@ -283,6 +283,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.user, self.password, self.apikey) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/sinch.py b/apprise/plugins/sinch.py index 06bd5b1e70..51cdea32b9 100644 --- a/apprise/plugins/sinch.py +++ b/apprise/plugins/sinch.py @@ -381,6 +381,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.service_plan_id, self.api_token, self.source, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/slack.py b/apprise/plugins/slack.py index bf69d5649c..fb4a8b6e01 100644 --- a/apprise/plugins/slack.py +++ b/apprise/plugins/slack.py @@ -326,6 +326,7 @@ def __init__(self, access_token=None, token_a=None, token_b=None, self.mode = SlackMode.BOT if access_token else SlackMode.WEBHOOK if self.mode is SlackMode.WEBHOOK: + self.access_token = None self.token_a = validate_regex( token_a, *self.template_tokens['token_a']['regex']) if not self.token_a: @@ -350,6 +351,9 @@ def __init__(self, access_token=None, token_a=None, token_b=None, self.logger.warning(msg) raise TypeError(msg) else: + self.token_a = None + self.token_b = None + self.token_c = None self.access_token = validate_regex( access_token, *self.template_tokens['access_token']['regex']) if not self.access_token: @@ -1018,6 +1022,18 @@ def _send(self, url, payload, attach=None, http_method='post', params=None, # Return the response for processing return response + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, self.token_a, self.token_b, self.token_c, + self.access_token, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/smseagle.py b/apprise/plugins/smseagle.py index 8eddca588d..8130834579 100644 --- a/apprise/plugins/smseagle.py +++ b/apprise/plugins/smseagle.py @@ -564,6 +564,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, attach=None, return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.token, self.host, self.port, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/smsmanager.py b/apprise/plugins/smsmanager.py index 1d352daf2d..a4552ad4b4 100644 --- a/apprise/plugins/smsmanager.py +++ b/apprise/plugins/smsmanager.py @@ -314,6 +314,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol[0], self.apikey) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/smtp2go.py b/apprise/plugins/smtp2go.py index 017da81110..cb8c71ff76 100644 --- a/apprise/plugins/smtp2go.py +++ b/apprise/plugins/smtp2go.py @@ -464,6 +464,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, attach=None, return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.user, self.host, self.apikey) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/sns.py b/apprise/plugins/sns.py index cc6e830767..9deb9f7b07 100644 --- a/apprise/plugins/sns.py +++ b/apprise/plugins/sns.py @@ -573,6 +573,18 @@ def _xml_iter(root, response): return response + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, self.aws_access_key_id, + self.aws_secret_access_key, self.aws_region_name, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/sparkpost.py b/apprise/plugins/sparkpost.py index b873d6b0ee..b1fb7bca0f 100644 --- a/apprise/plugins/sparkpost.py +++ b/apprise/plugins/sparkpost.py @@ -670,6 +670,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, attach=None, return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.user, self.apikey, self.host) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/splunk.py b/apprise/plugins/splunk.py index 3a4f107336..04727ba82f 100644 --- a/apprise/plugins/splunk.py +++ b/apprise/plugins/splunk.py @@ -382,6 +382,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol[0], self.routing_key, self.entity_id, + self.apikey, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/streamlabs.py b/apprise/plugins/streamlabs.py index c534f1ba62..9b718f8aec 100644 --- a/apprise/plugins/streamlabs.py +++ b/apprise/plugins/streamlabs.py @@ -376,6 +376,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.access_token) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/synology.py b/apprise/plugins/synology.py index ed85f80c0f..d29440b452 100644 --- a/apprise/plugins/synology.py +++ b/apprise/plugins/synology.py @@ -156,6 +156,19 @@ def __init__(self, token=None, headers=None, file_url=None, **kwargs): return + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, self.port, self.token, + self.fullpath.rstrip('/'), + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/syslog.py b/apprise/plugins/syslog.py index 935111eea3..0f552ebbb9 100644 --- a/apprise/plugins/syslog.py +++ b/apprise/plugins/syslog.py @@ -242,6 +242,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return self.protocol + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/techuluspush.py b/apprise/plugins/techuluspush.py index 682bf088e0..6296501480 100644 --- a/apprise/plugins/techuluspush.py +++ b/apprise/plugins/techuluspush.py @@ -184,6 +184,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.apikey) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/telegram.py b/apprise/plugins/telegram.py index 6b997f574b..9175fb3172 100644 --- a/apprise/plugins/telegram.py +++ b/apprise/plugins/telegram.py @@ -918,6 +918,15 @@ def _send_attachments(self, target, notify_type, attach): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.bot_token) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/threema.py b/apprise/plugins/threema.py index 423c231243..55293a1cb3 100644 --- a/apprise/plugins/threema.py +++ b/apprise/plugins/threema.py @@ -302,6 +302,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.user, self.secret) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/twilio.py b/apprise/plugins/twilio.py index 4205e37f0a..9c27c3467e 100644 --- a/apprise/plugins/twilio.py +++ b/apprise/plugins/twilio.py @@ -359,6 +359,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, self.account_sid, self.auth_token, + self.source, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/twist.py b/apprise/plugins/twist.py index 62d729f4fa..66f70f525f 100644 --- a/apprise/plugins/twist.py +++ b/apprise/plugins/twist.py @@ -229,6 +229,18 @@ def __init__(self, email=None, targets=None, **kwargs): self.default_notification_channel)) return + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol if self.secure else self.protocol, + self.user, self.password, self.host, self.port, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/twitter.py b/apprise/plugins/twitter.py index 8000a81518..369aaac0c8 100644 --- a/apprise/plugins/twitter.py +++ b/apprise/plugins/twitter.py @@ -780,6 +780,18 @@ def body_maxlen(self): """ return 10000 if self.mode == TwitterMessageMode.DM else 280 + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol[0], self.ckey, self.csecret, self.akey, + self.asecret, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/voipms.py b/apprise/plugins/voipms.py index 3a4e6d25f6..6a5d4d5a89 100644 --- a/apprise/plugins/voipms.py +++ b/apprise/plugins/voipms.py @@ -306,6 +306,17 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, self.email, self.password, self.source, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/vonage.py b/apprise/plugins/vonage.py index 441a6ba6b0..3a9b234176 100644 --- a/apprise/plugins/vonage.py +++ b/apprise/plugins/vonage.py @@ -307,6 +307,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol[0], self.apikey, self.secret) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/webexteams.py b/apprise/plugins/webexteams.py index bd0bdb5779..ccee386b53 100644 --- a/apprise/plugins/webexteams.py +++ b/apprise/plugins/webexteams.py @@ -207,6 +207,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol[0], self.token) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/wecombot.py b/apprise/plugins/wecombot.py index ab63417183..03282cd9f1 100644 --- a/apprise/plugins/wecombot.py +++ b/apprise/plugins/wecombot.py @@ -134,6 +134,15 @@ def __init__(self, key, **kwargs): ) return + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.key) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/whatsapp.py b/apprise/plugins/whatsapp.py index 7120d736c1..e0322b80d5 100644 --- a/apprise/plugins/whatsapp.py +++ b/apprise/plugins/whatsapp.py @@ -446,6 +446,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return (self.secure_protocol, self.from_phone_id, self.token) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/windows.py b/apprise/plugins/windows.py index 746fcd1dde..1c8df40458 100644 --- a/apprise/plugins/windows.py +++ b/apprise/plugins/windows.py @@ -210,6 +210,15 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return self.protocol + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/xbmc.py b/apprise/plugins/xbmc.py index 8006e10053..61e7b1e2e3 100644 --- a/apprise/plugins/xbmc.py +++ b/apprise/plugins/xbmc.py @@ -299,6 +299,25 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return True + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + default_schema = self.xbmc_protocol if ( + self.protocol <= self.xbmc_remote_protocol) else self.kodi_protocol + if self.secure: + # Append 's' to schema + default_schema += 's' + + port = self.port if self.port else ( + 443 if self.secure else self.xbmc_default_port) + return ( + default_schema, self.user, self.password, self.host, port, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/plugins/zulip.py b/apprise/plugins/zulip.py index e829e6f6d8..34c6d813e4 100644 --- a/apprise/plugins/zulip.py +++ b/apprise/plugins/zulip.py @@ -334,6 +334,18 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): return not has_error + @property + def url_identifier(self): + """ + Returns all of the identifiers that make this URL unique from + another simliar one. Targets or end points should never be identified + here. + """ + return ( + self.secure_protocol, self.organization, self.hostname, + self.token, + ) + def url(self, privacy=False, *args, **kwargs): """ Returns the URL built dynamically based on specified arguments. diff --git a/apprise/url.py b/apprise/url.py index 9499deb350..b2cbfbea17 100644 --- a/apprise/url.py +++ b/apprise/url.py @@ -294,6 +294,11 @@ def __init__(self, asset=None, **kwargs): 'Invalid Unique URL Identifier Salt value (salt) was ' 'specified {}'.format(kwargs.get('salt'))) + # Store our Timeout Variables + if 'cache' in kwargs and not parse_bool(kwargs.get('cache', True)): + # Enforce the disabling of cache (ortherwise defaults are use) + self.__url_identifier = False + if 'tag' in kwargs: # We want to associate some tags with our notification service. # the code below gets the 'tag' argument if defined, otherwise diff --git a/test/helpers/rest.py b/test/helpers/rest.py index c3ab5bcf26..e5a8fb53e0 100644 --- a/test/helpers/rest.py +++ b/test/helpers/rest.py @@ -201,6 +201,13 @@ def run(self, url, meta, mock_request, mock_post, mock_get): # this url assert isinstance(obj.url(), str) is True + # Test that we support a url identifier + url_id = obj.url_id() + + # It can be either disabled or a string; nothing else + assert isinstance(url_id, str) or \ + (url_id is None and obj.url_identifier is False) + # Verify we can acquire a target count as an integer assert isinstance(len(obj), int) @@ -230,6 +237,13 @@ def run(self, url, meta, mock_request, mock_post, mock_get): # from the one that was already created properly obj_cmp = Apprise.instantiate(obj.url()) + # Our new object should produce the same url identifier + if obj.url_identifier != obj_cmp.url_identifier: + print('Provided %s' % url) + raise AssertionError( + "URL Identifier: '{}' != expected '{}'".format( + obj_cmp.url_identifier, obj.url_identifier)) + # Our object should be the same instance as what we had # originally expected above. if not isinstance(obj_cmp, NotifyBase): diff --git a/test/test_api.py b/test/test_api.py index 75b57bb392..edf9d7ff67 100644 --- a/test/test_api.py +++ b/test/test_api.py @@ -880,22 +880,53 @@ def test_apprise_unique_id(): # Leverage salt setting obj2 = Apprise.instantiate('json://user@127.0.0.1/path/?salt=abcd') - assert obj1.url_id() != obj2.url_id() + assert obj1.url_id(lazy=False) != obj2.url_id(lazy=False) # same salt value produces a match again obj1 = Apprise.instantiate('json://user@127.0.0.1/path/?salt=abcd') assert obj1.url_id() == obj2.url_id() + # We'll add a good notification to our list + class TesNoURLID(NotifyBase): + """ + This class is just sets a use case where we don't return a + url_identifier + """ + + # we'll use this as a key to make our service easier to find + # in the next part of the testing + service_name = 'nourl' + + _url_identifier = False + + def send(self, **kwargs): + # Pretend everything is okay (so we don't break other tests) + return True + + @staticmethod + def parse_url(url): + return NotifyBase.parse_url(url, verify_host=False) + + @property + def url_identifier(self): + """ + No URL Identifier + """ + return self._url_identifier + + N_MGR['nourl'] = TesNoURLID + # setting URL Identifier to False disables the generator - url = 'json://user@127.0.0.1/path/?arg' + url = 'nourl://' obj = Apprise.instantiate(url) - obj.url_identifier = False # No generation takes place assert obj.url_id() is None + # # Dictionary Testing # - obj.url_identifier = {'abc': '123', 'def': b'\0', 'hij': 42, 'klm': object} + obj._url_identifier = { + 'abc': '123', 'def': b'\0', 'hij': 42, 'klm': object} # call uses cached value (from above) assert obj.url_id() is None # Tests dictionary key generation @@ -904,31 +935,31 @@ def test_apprise_unique_id(): # List/Set/Tuple Testing # obj1 = Apprise.instantiate(url) - obj1.url_identifier = ['123', b'\0', 42, object] + obj1._url_identifier = ['123', b'\0', 42, object] # Tests dictionary key generation assert obj1.url_id() is not None obj2 = Apprise.instantiate(url) - obj2.url_identifier = ('123', b'\0', 42, object) + obj2._url_identifier = ('123', b'\0', 42, object) assert obj2.url_id() is not None assert obj2.url_id() == obj2.url_id() obj3 = Apprise.instantiate(url) - obj3.url_identifier = set(['123', b'\0', 42, object]) + obj3._url_identifier = set(['123', b'\0', 42, object]) assert obj3.url_id() is not None obj = Apprise.instantiate(url) - obj.url_identifier = b'test' + obj._url_identifier = b'test' assert obj.url_id() is not None obj = Apprise.instantiate(url) - obj.url_identifier = 'test' + obj._url_identifier = 'test' assert obj.url_id() is not None # Testing Garbage for x in (31, object, 43.1): obj = Apprise.instantiate(url) - obj.url_identifier = x + obj._url_identifier = x assert obj.url_id() is not None diff --git a/test/test_plugin_aprs.py b/test/test_plugin_aprs.py index 2399c95623..11a0d55086 100644 --- a/test/test_plugin_aprs.py +++ b/test/test_plugin_aprs.py @@ -154,6 +154,9 @@ def test_plugin_aprs_urls(mock_create_connection): # We still instantiate assert isinstance(instance, NotifyAprs) + # Test that we generate ourselves a unique id + assert instance.url_id() == '81b567c5c4df946e2925cf68f4c76778cfca13df' + # We still load our bad entries assert instance.url(privacy=True).startswith( "aprs://DF1JSL-15:****@A...I/A...A?")