mirror of
https://github.com/caronc/apprise-api.git
synced 2024-12-12 18:00:51 +01:00
Support "attach" keyword (alias of "attachment") (#173)
This commit is contained in:
parent
b4805f01e1
commit
479a3bd6ed
14
README.md
14
README.md
@ -168,6 +168,13 @@ curl -X POST -d 'urls=mailto://user:pass@gmail.com' \
|
|||||||
curl -X POST -d '{"urls": "mailto://user:pass@gmail.com", "body":"test message"}' \
|
curl -X POST -d '{"urls": "mailto://user:pass@gmail.com", "body":"test message"}' \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
http://localhost:8000/notify
|
http://localhost:8000/notify
|
||||||
|
|
||||||
|
# attach= is an alias of attachment=
|
||||||
|
# Send a notification with a URL based attachment
|
||||||
|
curl -X POST \
|
||||||
|
-F 'urls=mailto://user:pass@gmail.com' \
|
||||||
|
-F attach=attach=https://raw.githubusercontent.com/caronc/apprise/master/apprise/assets/themes/default/apprise-logo.png \
|
||||||
|
http://localhost:8000/notify
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also send notifications that are URLs. Apprise will download the item so that it can send it along to all end points that should be notified about it.
|
You can also send notifications that are URLs. Apprise will download the item so that it can send it along to all end points that should be notified about it.
|
||||||
@ -252,6 +259,13 @@ curl -X POST \
|
|||||||
-F attach1=@Screenshot-1.png \
|
-F attach1=@Screenshot-1.png \
|
||||||
-F attach2=@/my/path/to/Apprise.doc \
|
-F attach2=@/my/path/to/Apprise.doc \
|
||||||
http://localhost:8000/notify/abc123
|
http://localhost:8000/notify/abc123
|
||||||
|
|
||||||
|
# attach= is an alias of attachment=
|
||||||
|
# Send a notification with a URL based attachment
|
||||||
|
curl -X POST \
|
||||||
|
-F 'urls=mailto://user:pass@gmail.com' \
|
||||||
|
-F attach=attach=https://raw.githubusercontent.com/caronc/apprise/master/apprise/assets/themes/default/apprise-logo.png \
|
||||||
|
http://localhost:8000/notify/abc123
|
||||||
```
|
```
|
||||||
|
|
||||||
🏷️ You can also leverage *tagging* which allows you to associate one or more tags with your Apprise URLs. By doing this, notifications only need to be referred to by their easy to remember notify tag name such as `devops`, `admin`, `family`, etc. You can very easily group more than one notification service under the same *tag* allowing you to notify a group of services at once. This is accomplished through configuration files ([documented here](https://github.com/caronc/apprise/wiki/config)) that can be saved to the persistent storage previously associated with a `{KEY}`.
|
🏷️ You can also leverage *tagging* which allows you to associate one or more tags with your Apprise URLs. By doing this, notifications only need to be referred to by their easy to remember notify tag name such as `devops`, `admin`, `family`, etc. You can very easily group more than one notification service under the same *tag* allowing you to notify a group of services at once. This is accomplished through configuration files ([documented here](https://github.com/caronc/apprise/wiki/config)) that can be saved to the persistent storage previously associated with a `{KEY}`.
|
||||||
|
@ -115,6 +115,12 @@
|
|||||||
-F attach1=@Screenshot-1.png \<br/>
|
-F attach1=@Screenshot-1.png \<br/>
|
||||||
-F attach2=@/my/path/to/Apprise.doc \<br/>
|
-F attach2=@/my/path/to/Apprise.doc \<br/>
|
||||||
http{% if request.is_secure %}s{% endif %}://{{request.META.HTTP_HOST}}{{BASE_URL}}/notify/<em>{{key}}</em></code></pre>
|
http{% if request.is_secure %}s{% endif %}://{{request.META.HTTP_HOST}}{{BASE_URL}}/notify/<em>{{key}}</em></code></pre>
|
||||||
|
{% blocktrans %}Sends a notification to our endpoints with an attachment{% endblocktrans %}
|
||||||
|
<pre><code class="bash">
|
||||||
|
curl -X POST \<br/>
|
||||||
|
-F "tag=all" \ <br/>
|
||||||
|
-F "attach=https://raw.githubusercontent.com/caronc/apprise/master/apprise/assets/themes/default/apprise-logo.png" \ <br/>
|
||||||
|
"{{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/notify/<em>{{key}}</em>"</code></pre>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
|
@ -99,6 +99,11 @@
|
|||||||
-F attach2=@Screenshot-2.png \ <br/>
|
-F attach2=@Screenshot-2.png \ <br/>
|
||||||
"{{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/notify/"
|
"{{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/notify/"
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
<pre><code class="bash">
|
||||||
|
# {% blocktrans %}Send an web based file attachment to a <a href="https://github.com/caronc/apprise/wiki/Notify_discord" target="_blank">Discord</a> server:{% endblocktrans %}<br/>
|
||||||
|
curl -X POST -F 'urls=discord://credentials' \<br/>
|
||||||
|
-F "attach=https://raw.githubusercontent.com/caronc/apprise/master/apprise/assets/themes/default/apprise-logo.png" \ <br/>
|
||||||
|
"{{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/notify/"</code></pre>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@ -492,6 +497,12 @@
|
|||||||
-F "tag=all" \ <br/>
|
-F "tag=all" \ <br/>
|
||||||
-F "body=test body" \ <br/>
|
-F "body=test body" \ <br/>
|
||||||
-F "title=test title" \ <br/>
|
-F "title=test title" \ <br/>
|
||||||
|
"{{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/notify/<em>{{key}}</em>"</code></pre>
|
||||||
|
<pre><code class="bash">
|
||||||
|
# {% blocktrans %}Sends a notification to our endpoints with an attachment{% endblocktrans %}<br/>
|
||||||
|
curl -X POST \<br/>
|
||||||
|
-F "tag=all" \ <br/>
|
||||||
|
-F "attach=https://raw.githubusercontent.com/caronc/apprise/master/apprise/assets/themes/default/apprise-logo.png" \ <br/>
|
||||||
"{{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/notify/<em>{{key}}</em>"</code></pre>
|
"{{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/notify/<em>{{key}}</em>"</code></pre>
|
||||||
<pre><code class="bash">
|
<pre><code class="bash">
|
||||||
# {% blocktrans %}Notifies all URLs assigned the <em>devops</em> tag{% endblocktrans %}<br/>
|
# {% blocktrans %}Notifies all URLs assigned the <em>devops</em> tag{% endblocktrans %}<br/>
|
||||||
|
@ -847,6 +847,22 @@ class NotifyTests(SimpleTestCase):
|
|||||||
assert response.status_code == 400
|
assert response.status_code == 400
|
||||||
assert mock_notify.call_count == 0
|
assert mock_notify.call_count == 0
|
||||||
|
|
||||||
|
# Reset our mock object
|
||||||
|
mock_notify.reset_mock()
|
||||||
|
|
||||||
|
# Preare our form data
|
||||||
|
form_data = {
|
||||||
|
'body': 'test notifiction',
|
||||||
|
'attach': 'https://localhost/invalid/path/to/image.png',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Send our notification
|
||||||
|
response = self.client.post(
|
||||||
|
'/notify/{}'.format(key), form_data)
|
||||||
|
# We fail because we couldn't retrieve our attachment
|
||||||
|
assert response.status_code == 400
|
||||||
|
assert mock_notify.call_count == 0
|
||||||
|
|
||||||
@mock.patch('apprise.Apprise.notify')
|
@mock.patch('apprise.Apprise.notify')
|
||||||
def test_notify_by_loaded_urls_with_json(self, mock_notify):
|
def test_notify_by_loaded_urls_with_json(self, mock_notify):
|
||||||
"""
|
"""
|
||||||
@ -998,11 +1014,38 @@ class NotifyTests(SimpleTestCase):
|
|||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert mock_notify.call_count == 1
|
assert mock_notify.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
# Reset our mock object
|
# Reset our mock object
|
||||||
mock_notify.reset_mock()
|
mock_notify.reset_mock()
|
||||||
|
|
||||||
|
# If an empty format is specified, it is accepted and
|
||||||
|
# no imput format is specified
|
||||||
|
json_data = {
|
||||||
|
'body': 'test message',
|
||||||
|
'format': None,
|
||||||
|
'attach': 'https://localhost/invalid/path/to/image.png',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test case with format changed
|
||||||
|
response = self.client.post(
|
||||||
|
'/notify/{}'.format(key),
|
||||||
|
data=json.dumps(json_data),
|
||||||
|
content_type='application/json',
|
||||||
|
)
|
||||||
|
|
||||||
|
# We failed to send notification because we couldn't fetch the
|
||||||
|
# attachment
|
||||||
|
assert response.status_code == 400
|
||||||
|
assert mock_notify.call_count == 0
|
||||||
|
|
||||||
|
# Reset our mock object
|
||||||
|
mock_notify.reset_mock()
|
||||||
|
|
||||||
|
json_data = {
|
||||||
|
'body': 'test message',
|
||||||
|
}
|
||||||
|
|
||||||
# Same results for any empty string:
|
# Same results for any empty string:
|
||||||
json_data['format'] = ''
|
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
'/notify/{}'.format(key),
|
'/notify/{}'.format(key),
|
||||||
data=json.dumps(json_data),
|
data=json.dumps(json_data),
|
||||||
|
@ -250,6 +250,49 @@ class StatelessNotifyTests(SimpleTestCase):
|
|||||||
assert response.status_code == 400
|
assert response.status_code == 400
|
||||||
assert mock_notify.call_count == 0
|
assert mock_notify.call_count == 0
|
||||||
|
|
||||||
|
# Reset our mock object
|
||||||
|
mock_notify.reset_mock()
|
||||||
|
|
||||||
|
# Preare our form data (support attach keyword)
|
||||||
|
form_data = {
|
||||||
|
'body': 'test notifiction',
|
||||||
|
'urls': ', '.join([
|
||||||
|
'mailto://user:pass@hotmail.com',
|
||||||
|
'mailto://user:pass@gmail.com',
|
||||||
|
]),
|
||||||
|
'attach': 'https://localhost/invalid/path/to/image.png',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Send our notification
|
||||||
|
response = self.client.post('/notify', form_data)
|
||||||
|
# We fail because we couldn't retrieve our attachment
|
||||||
|
assert response.status_code == 400
|
||||||
|
assert mock_notify.call_count == 0
|
||||||
|
|
||||||
|
# Reset our mock object
|
||||||
|
mock_notify.reset_mock()
|
||||||
|
|
||||||
|
# Preare our json data (and support attach keyword as alias)
|
||||||
|
json_data = {
|
||||||
|
'body': 'test notifiction',
|
||||||
|
'urls': ', '.join([
|
||||||
|
'mailto://user:pass@hotmail.com',
|
||||||
|
'mailto://user:pass@gmail.com',
|
||||||
|
]),
|
||||||
|
'attach': 'https://localhost/invalid/path/to/image.png',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Same results
|
||||||
|
response = self.client.post(
|
||||||
|
'/notify/',
|
||||||
|
data=json.dumps(json_data),
|
||||||
|
content_type='application/json',
|
||||||
|
)
|
||||||
|
|
||||||
|
# We fail because we couldn't retrieve our attachment
|
||||||
|
assert response.status_code == 400
|
||||||
|
assert mock_notify.call_count == 0
|
||||||
|
|
||||||
@override_settings(APPRISE_RECURSION_MAX=1)
|
@override_settings(APPRISE_RECURSION_MAX=1)
|
||||||
@mock.patch('apprise.Apprise.notify')
|
@mock.patch('apprise.Apprise.notify')
|
||||||
def test_stateless_notify_recursion(self, mock_notify):
|
def test_stateless_notify_recursion(self, mock_notify):
|
||||||
|
@ -610,9 +610,19 @@ class NotifyView(View):
|
|||||||
|
|
||||||
# Handle Attachments
|
# Handle Attachments
|
||||||
attach = None
|
attach = None
|
||||||
if not content.get('attachment') and 'attachment' in request.POST:
|
if not content.get('attachment'):
|
||||||
# Acquire attachments to work with them
|
if 'attachment' in request.POST:
|
||||||
content['attachment'] = request.POST.getlist('attachment')
|
# Acquire attachments to work with them
|
||||||
|
content['attachment'] = request.POST.getlist('attachment')
|
||||||
|
|
||||||
|
elif 'attach' in request.POST:
|
||||||
|
# Acquire kw (alias) attach to work with them
|
||||||
|
content['attachment'] = request.POST.getlist('attach')
|
||||||
|
|
||||||
|
elif content.get('attach'):
|
||||||
|
# Acquire kw (alias) attach from payload to work with
|
||||||
|
content['attachment'] = content['attach']
|
||||||
|
del content['attach']
|
||||||
|
|
||||||
if 'attachment' in content or request.FILES:
|
if 'attachment' in content or request.FILES:
|
||||||
try:
|
try:
|
||||||
@ -1148,9 +1158,19 @@ class StatelessNotifyView(View):
|
|||||||
|
|
||||||
# Handle Attachments
|
# Handle Attachments
|
||||||
attach = None
|
attach = None
|
||||||
if not content.get('attachment') and 'attachment' in request.POST:
|
if not content.get('attachment'):
|
||||||
# Acquire attachments to work with them
|
if 'attachment' in request.POST:
|
||||||
content['attachment'] = request.POST.getlist('attachment')
|
# Acquire attachments to work with them
|
||||||
|
content['attachment'] = request.POST.getlist('attachment')
|
||||||
|
|
||||||
|
elif 'attach' in request.POST:
|
||||||
|
# Acquire kw (alias) attach to work with them
|
||||||
|
content['attachment'] = request.POST.getlist('attach')
|
||||||
|
|
||||||
|
elif content.get('attach'):
|
||||||
|
# Acquire kw (alias) attach from payload to work with
|
||||||
|
content['attachment'] = content['attach']
|
||||||
|
del content['attach']
|
||||||
|
|
||||||
if 'attachment' in content or request.FILES:
|
if 'attachment' in content or request.FILES:
|
||||||
try:
|
try:
|
||||||
@ -1158,6 +1178,11 @@ class StatelessNotifyView(View):
|
|||||||
content.get('attachment'), request.FILES)
|
content.get('attachment'), request.FILES)
|
||||||
|
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
|
# Invalid entry found in list
|
||||||
|
logger.warning(
|
||||||
|
'NOTIFY - %s - Bad attachment specified',
|
||||||
|
request.META['REMOTE_ADDR'])
|
||||||
|
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
_('Bad attachment'),
|
_('Bad attachment'),
|
||||||
status=ResponseCode.bad_request)
|
status=ResponseCode.bad_request)
|
||||||
|
Loading…
Reference in New Issue
Block a user