diff --git a/changedetectionio/apprise_plugin/__init__.py b/changedetectionio/apprise_plugin/__init__.py new file mode 100644 index 00000000..93c382fa --- /dev/null +++ b/changedetectionio/apprise_plugin/__init__.py @@ -0,0 +1,78 @@ +# include the decorator +from apprise.decorators import notify + +@notify(on="delete") +@notify(on="deletes") +@notify(on="get") +@notify(on="gets") +@notify(on="post") +@notify(on="posts") +@notify(on="put") +@notify(on="puts") +def apprise_custom_api_call_wrapper(body, title, notify_type, *args, **kwargs): + import requests + import json + from apprise.utils import parse_url as apprise_parse_url + from apprise import URLBase + + url = kwargs['meta'].get('url') + + if url.startswith('post'): + r = requests.post + elif url.startswith('get'): + r = requests.get + elif url.startswith('put'): + r = requests.put + elif url.startswith('delete'): + r = requests.delete + + url = url.replace('post://', 'http://') + url = url.replace('posts://', 'https://') + url = url.replace('put://', 'http://') + url = url.replace('puts://', 'https://') + url = url.replace('get://', 'http://') + url = url.replace('gets://', 'https://') + url = url.replace('put://', 'http://') + url = url.replace('puts://', 'https://') + url = url.replace('delete://', 'http://') + url = url.replace('deletes://', 'https://') + + headers = {} + params = {} + auth = None + + # Convert /foobar?+some-header=hello to proper header dictionary + results = apprise_parse_url(url) + if results: + # Add our headers that the user can potentially over-ride if they wish + # to to our returned result set and tidy entries by unquoting them + headers = {URLBase.unquote(x): URLBase.unquote(y) + for x, y in results['qsd+'].items()} + + # https://github.com/caronc/apprise/wiki/Notify_Custom_JSON#get-parameter-manipulation + # In Apprise, it relies on prefixing each request arg with "-", because it uses say &method=update as a flag for apprise + # but here we are making straight requests, so we need todo convert this against apprise's logic + for k, v in results['qsd'].items(): + if not k.strip('+-') in results['qsd+'].keys(): + params[URLBase.unquote(k)] = URLBase.unquote(v) + + # Determine Authentication + auth = '' + if results.get('user') and results.get('password'): + auth = (URLBase.unquote(results.get('user')), URLBase.unquote(results.get('user'))) + elif results.get('user'): + auth = (URLBase.unquote(results.get('user'))) + + # Try to auto-guess if it's JSON + try: + json.loads(body) + headers['Content-Type'] = 'application/json; charset=utf-8' + except ValueError as e: + pass + + r(results.get('url'), + auth=auth, + data=body.encode('utf-8') if type(body) is str else body, + headers=headers, + params=params + ) \ No newline at end of file diff --git a/changedetectionio/blueprint/browser_steps/browser_steps.py b/changedetectionio/blueprint/browser_steps/browser_steps.py index 6f38be2e..b9765bac 100644 --- a/changedetectionio/blueprint/browser_steps/browser_steps.py +++ b/changedetectionio/blueprint/browser_steps/browser_steps.py @@ -25,6 +25,7 @@ browser_step_ui_config = {'Choose one': '0 0', 'Click element if exists': '1 0', 'Click element': '1 0', 'Click element containing text': '0 1', + 'Click element containing text if exists': '0 1', 'Enter text in field': '1 1', 'Execute JS': '0 1', # 'Extract text and use as filter': '1 0', @@ -96,12 +97,24 @@ class steppable_browser_interface(): return self.action_goto_url(value=self.start_url) def action_click_element_containing_text(self, selector=None, value=''): + logger.debug("Clicking element containing text") if not len(value.strip()): return elem = self.page.get_by_text(value) if elem.count(): elem.first.click(delay=randint(200, 500), timeout=3000) + def action_click_element_containing_text_if_exists(self, selector=None, value=''): + logger.debug("Clicking element containing text if exists") + if not len(value.strip()): + return + elem = self.page.get_by_text(value) + logger.debug(f"Clicking element containing text - {elem.count()} elements found") + if elem.count(): + elem.first.click(delay=randint(200, 500), timeout=3000) + else: + return + def action_enter_text_in_field(self, selector, value): if not len(selector.strip()): return diff --git a/changedetectionio/blueprint/tags/templates/edit-tag.html b/changedetectionio/blueprint/tags/templates/edit-tag.html index 2ccc68a0..a713cf6a 100644 --- a/changedetectionio/blueprint/tags/templates/edit-tag.html +++ b/changedetectionio/blueprint/tags/templates/edit-tag.html @@ -58,9 +58,9 @@ xpath://body/div/span[contains(@class, 'example-class')]", {% if '/text()' in field %} Note!: //text() function does not work where the <element> contains <![CDATA[]]>
{% endif %} - One rule per line, any rules that matches will be used.
- -