mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2025-12-15 12:36:53 +00:00
Support for standard API calls post:// posts:// get:// gets:// delete:// deletes:// put:// puts://
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import apprise
|
import apprise
|
||||||
from jinja2 import Environment, BaseLoader
|
from jinja2 import Environment, BaseLoader
|
||||||
from apprise import NotifyFormat
|
from apprise import NotifyFormat
|
||||||
|
import json
|
||||||
|
|
||||||
valid_tokens = {
|
valid_tokens = {
|
||||||
'base_url': '',
|
'base_url': '',
|
||||||
@@ -28,6 +29,53 @@ valid_notification_formats = {
|
|||||||
default_notification_format_for_watch: default_notification_format_for_watch
|
default_notification_format_for_watch: default_notification_format_for_watch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 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
|
||||||
|
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://')
|
||||||
|
|
||||||
|
# Try to auto-guess if it's JSON
|
||||||
|
headers = {}
|
||||||
|
try:
|
||||||
|
json.loads(body)
|
||||||
|
headers = {'Content-Type': 'application/json; charset=utf-8'}
|
||||||
|
except ValueError as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
r(url, headers=headers, data=body)
|
||||||
|
|
||||||
|
|
||||||
def process_notification(n_object, datastore):
|
def process_notification(n_object, datastore):
|
||||||
|
|
||||||
# Insert variables into the notification content
|
# Insert variables into the notification content
|
||||||
@@ -63,7 +111,12 @@ def process_notification(n_object, datastore):
|
|||||||
|
|
||||||
# So if no avatar_url is specified, add one so it can be correctly calculated into the total payload
|
# So if no avatar_url is specified, add one so it can be correctly calculated into the total payload
|
||||||
k = '?' if not '?' in url else '&'
|
k = '?' if not '?' in url else '&'
|
||||||
if not 'avatar_url' in url and not url.startswith('mail'):
|
if not 'avatar_url' in url \
|
||||||
|
and not url.startswith('mail') \
|
||||||
|
and not url.startswith('post') \
|
||||||
|
and not url.startswith('get') \
|
||||||
|
and not url.startswith('delete') \
|
||||||
|
and not url.startswith('put'):
|
||||||
url += k + 'avatar_url=https://raw.githubusercontent.com/dgtlmoon/changedetection.io/master/changedetectionio/static/images/avatar-256x256.png'
|
url += k + 'avatar_url=https://raw.githubusercontent.com/dgtlmoon/changedetection.io/master/changedetectionio/static/images/avatar-256x256.png'
|
||||||
|
|
||||||
if url.startswith('tgram://'):
|
if url.startswith('tgram://'):
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<li><code>discord://</code> only supports a maximum <strong>2,000 characters</strong> of notification text, including the title.</li>
|
<li><code>discord://</code> only supports a maximum <strong>2,000 characters</strong> of notification text, including the title.</li>
|
||||||
<li><code>tgram://</code> bots cant send messages to other bots, so you should specify chat ID of non-bot user.</li>
|
<li><code>tgram://</code> bots cant send messages to other bots, so you should specify chat ID of non-bot user.</li>
|
||||||
<li><code>tgram://</code> only supports very limited HTML and can fail when extra tags are sent, <a href="https://core.telegram.org/bots/api#html-style">read more here</a> (or use plaintext/markdown format)</li>
|
<li><code>tgram://</code> only supports very limited HTML and can fail when extra tags are sent, <a href="https://core.telegram.org/bots/api#html-style">read more here</a> (or use plaintext/markdown format)</li>
|
||||||
<li><code>GET</code> & <code>POST</code> requests use <code>json://</code> or <code>jsons://</code>, use <code>-</code> before each arg, for example <code>jsons://foobar.com?-id={% raw -%}{{watch_uuid}}{%- endraw %}</code> <a href="https://github.com/caronc/apprise/wiki/Notify_Custom_JSON#get-parameter-manipulation">read more here</a> </li>
|
<li><code>gets://</code>, <code>posts://</code>, <code>puts://</code>, <code>deletes://</code> for direct API calls (or omit the "<code>s</code>" for non-SSL ie <code>get://</code>)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="notifications-wrapper">
|
<div class="notifications-wrapper">
|
||||||
|
|||||||
@@ -237,7 +237,6 @@ def test_check_notification(client, live_server):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_notification_validation(client, live_server):
|
def test_notification_validation(client, live_server):
|
||||||
#live_server_setup(live_server)
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
# re #242 - when you edited an existing new entry, it would not correctly show the notification settings
|
# re #242 - when you edited an existing new entry, it would not correctly show the notification settings
|
||||||
@@ -309,19 +308,24 @@ def test_notification_jinja2(client, live_server):
|
|||||||
# test_endpoint - that sends the contents of a file
|
# test_endpoint - that sends the contents of a file
|
||||||
# test_notification_endpoint - that takes a POST and writes it to file (test-datastore/notification.txt)
|
# test_notification_endpoint - that takes a POST and writes it to file (test-datastore/notification.txt)
|
||||||
|
|
||||||
test_notification_url = url_for('test_notification_endpoint', _external=True).replace('http://', 'json://')
|
# CUSTOM JSON BODY CHECK for POST://
|
||||||
|
set_original_response()
|
||||||
|
test_notification_url = url_for('test_notification_endpoint', _external=True).replace('http://', 'post://')+"?xxx={{ watch_url }}"
|
||||||
|
|
||||||
res = client.post(
|
res = client.post(
|
||||||
url_for("settings_page"),
|
url_for("settings_page"),
|
||||||
data={"application-notification_title": "New ChangeDetection.io Notification - {{ watch_url }}",
|
data={"application-notification_title": "New ChangeDetection.io Notification - {{ watch_url }}",
|
||||||
"application-notification_body": "Got {{ watch_url }}\n",
|
"application-notification_body": '{ "url" : "{{ watch_url }}", "secret": 444 }',
|
||||||
# https://github.com/caronc/apprise/wiki/Notify_Custom_JSON#get-parameter-manipulation
|
# https://github.com/caronc/apprise/wiki/Notify_Custom_JSON#get-parameter-manipulation
|
||||||
"application-notification_urls": test_notification_url+"?-XXX={{ watch_url }}",
|
"application-notification_urls": test_notification_url,
|
||||||
"application-minutes_between_check": 180,
|
"application-minutes_between_check": 180,
|
||||||
"application-fetch_backend": "html_requests"
|
"application-fetch_backend": "html_requests"
|
||||||
},
|
},
|
||||||
follow_redirects=True
|
follow_redirects=True
|
||||||
)
|
)
|
||||||
|
assert b'Settings updated' in res.data
|
||||||
|
|
||||||
|
# Add a watch and trigger a HTTP POST
|
||||||
test_url = url_for('test_endpoint', _external=True)
|
test_url = url_for('test_endpoint', _external=True)
|
||||||
res = client.post(
|
res = client.post(
|
||||||
url_for("form_quick_watch_add"),
|
url_for("form_quick_watch_add"),
|
||||||
@@ -330,25 +334,22 @@ def test_notification_jinja2(client, live_server):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert b"Watch added" in res.data
|
assert b"Watch added" in res.data
|
||||||
time.sleep(2)
|
|
||||||
set_more_modified_response()
|
|
||||||
client.get(url_for("form_watch_checknow"), follow_redirects=True)
|
|
||||||
time.sleep(3)
|
|
||||||
|
|
||||||
# URL check
|
time.sleep(2)
|
||||||
|
set_modified_response()
|
||||||
|
|
||||||
|
client.get(url_for("form_watch_checknow"), follow_redirects=True)
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
with open("test-datastore/notification.txt", 'r') as f:
|
||||||
|
x=f.read()
|
||||||
|
j = json.loads(x)
|
||||||
|
assert j['url'].startswith('http://localhost')
|
||||||
|
assert j['secret'] == 444
|
||||||
|
|
||||||
|
# URL check, this will always be converted to lowercase
|
||||||
assert os.path.isfile("test-datastore/notification-url.txt")
|
assert os.path.isfile("test-datastore/notification-url.txt")
|
||||||
with open("test-datastore/notification-url.txt", 'r') as f:
|
with open("test-datastore/notification-url.txt", 'r') as f:
|
||||||
notification = f.read()
|
notification_url = f.read()
|
||||||
|
assert 'xxx=http' in notification_url
|
||||||
assert 'XXX=http' in notification
|
|
||||||
os.unlink("test-datastore/notification-url.txt")
|
os.unlink("test-datastore/notification-url.txt")
|
||||||
|
|
||||||
# BODY and TITLE check
|
|
||||||
assert os.path.isfile("test-datastore/notification.txt")
|
|
||||||
with open("test-datastore/notification.txt", 'r') as f:
|
|
||||||
notification = json.loads(f.read())
|
|
||||||
assert notification
|
|
||||||
|
|
||||||
assert 'New ChangeDetection.io Notification - http://localhost' in notification['title']
|
|
||||||
assert 'Got http://localhost' in notification['message']
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user