mirror of
https://github.com/caronc/apprise.git
synced 2024-11-25 09:33:50 +01:00
Added Attachment Support for Apprise API (#873)
This commit is contained in:
parent
00ddb098e5
commit
b327abf134
@ -684,6 +684,7 @@ class Apprise:
|
||||
'setup_url': getattr(plugin, 'setup_url', None),
|
||||
# Placeholder - populated below
|
||||
'details': None,
|
||||
|
||||
# Differentiat between what is a custom loaded plugin and
|
||||
# which is native.
|
||||
'category': getattr(plugin, 'category', None)
|
||||
|
@ -33,6 +33,7 @@
|
||||
import re
|
||||
import requests
|
||||
from json import dumps
|
||||
import base64
|
||||
|
||||
from .NotifyBase import NotifyBase
|
||||
from ..URLBase import PrivacyMode
|
||||
@ -209,15 +210,51 @@ class NotifyAppriseAPI(NotifyBase):
|
||||
token=self.pprint(self.token, privacy, safe=''),
|
||||
params=NotifyAppriseAPI.urlencode(params))
|
||||
|
||||
def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs):
|
||||
def send(self, body, title='', notify_type=NotifyType.INFO, attach=None,
|
||||
**kwargs):
|
||||
"""
|
||||
Perform Apprise API Notification
|
||||
"""
|
||||
|
||||
headers = {}
|
||||
# Prepare HTTP Headers
|
||||
headers = {
|
||||
'User-Agent': self.app_id,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
# Apply any/all header over-rides defined
|
||||
headers.update(self.headers)
|
||||
|
||||
# Track our potential attachments
|
||||
attachments = []
|
||||
if attach:
|
||||
for attachment in attach:
|
||||
# Perform some simple error checking
|
||||
if not attachment:
|
||||
# We could not access the attachment
|
||||
self.logger.error(
|
||||
'Could not access attachment {}.'.format(
|
||||
attachment.url(privacy=True)))
|
||||
return False
|
||||
|
||||
try:
|
||||
with open(attachment.path, 'rb') as f:
|
||||
# Output must be in a DataURL format (that's what
|
||||
# PushSafer calls it):
|
||||
attachments.append({
|
||||
'filename': attachment.name,
|
||||
'base64': base64.b64encode(f.read())
|
||||
.decode('utf-8'),
|
||||
'mimetype': attachment.mimetype,
|
||||
})
|
||||
|
||||
except (OSError, IOError) as e:
|
||||
self.logger.warning(
|
||||
'An I/O error occurred while reading {}.'.format(
|
||||
attachment.name if attachment else 'attachment'))
|
||||
self.logger.debug('I/O Exception: %s' % str(e))
|
||||
return False
|
||||
|
||||
# prepare Apprise API Object
|
||||
payload = {
|
||||
# Apprise API Payload
|
||||
@ -225,6 +262,7 @@ class NotifyAppriseAPI(NotifyBase):
|
||||
'body': body,
|
||||
'type': notify_type,
|
||||
'format': self.notify_format,
|
||||
'attachments': attachments,
|
||||
}
|
||||
|
||||
if self.__tags:
|
||||
|
@ -30,14 +30,22 @@
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import os
|
||||
from unittest import mock
|
||||
from apprise.plugins.NotifyAppriseAPI import NotifyAppriseAPI
|
||||
from helpers import AppriseURLTester
|
||||
import requests
|
||||
from apprise import Apprise
|
||||
from apprise import AppriseAttachment
|
||||
from apprise import NotifyType
|
||||
|
||||
# Disable logging for a cleaner testing output
|
||||
import logging
|
||||
logging.disable(logging.CRITICAL)
|
||||
|
||||
# Attachment Directory
|
||||
TEST_VAR_DIR = os.path.join(os.path.dirname(__file__), 'var')
|
||||
|
||||
# Our Testing URLs
|
||||
apprise_url_tests = (
|
||||
('apprise://', {
|
||||
@ -172,3 +180,62 @@ def test_plugin_apprise_urls():
|
||||
|
||||
# Run our general tests
|
||||
AppriseURLTester(tests=apprise_url_tests).run_all()
|
||||
|
||||
|
||||
@mock.patch('requests.post')
|
||||
def test_notify_apprise_api_attachments(mock_post):
|
||||
"""
|
||||
NotifyAppriseAPI() Attachments
|
||||
|
||||
"""
|
||||
|
||||
okay_response = requests.Request()
|
||||
okay_response.status_code = requests.codes.ok
|
||||
okay_response.content = ""
|
||||
|
||||
# Assign our mock object our return value
|
||||
mock_post.return_value = okay_response
|
||||
|
||||
obj = Apprise.instantiate('apprise://user@localhost/mytoken1/')
|
||||
assert isinstance(obj, NotifyAppriseAPI)
|
||||
|
||||
# Test Valid Attachment
|
||||
path = os.path.join(TEST_VAR_DIR, 'apprise-test.gif')
|
||||
attach = AppriseAttachment(path)
|
||||
assert obj.notify(
|
||||
body='body', title='title', notify_type=NotifyType.INFO,
|
||||
attach=attach) is True
|
||||
|
||||
# Test invalid attachment
|
||||
path = os.path.join(TEST_VAR_DIR, '/invalid/path/to/an/invalid/file.jpg')
|
||||
assert obj.notify(
|
||||
body='body', title='title', notify_type=NotifyType.INFO,
|
||||
attach=path) is False
|
||||
|
||||
# Test Valid Attachment (load 3)
|
||||
path = (
|
||||
os.path.join(TEST_VAR_DIR, 'apprise-test.gif'),
|
||||
os.path.join(TEST_VAR_DIR, 'apprise-test.gif'),
|
||||
os.path.join(TEST_VAR_DIR, 'apprise-test.gif'),
|
||||
)
|
||||
attach = AppriseAttachment(path)
|
||||
|
||||
# Return our good configuration
|
||||
mock_post.side_effect = None
|
||||
mock_post.return_value = okay_response
|
||||
with mock.patch('builtins.open', side_effect=OSError()):
|
||||
# We can't send the message we can't open the attachment for reading
|
||||
assert obj.notify(
|
||||
body='body', title='title', notify_type=NotifyType.INFO,
|
||||
attach=attach) is False
|
||||
|
||||
# test the handling of our batch modes
|
||||
obj = Apprise.instantiate('apprise://user@localhost/mytoken1/')
|
||||
assert isinstance(obj, NotifyAppriseAPI)
|
||||
|
||||
# Now send an attachment normally without issues
|
||||
mock_post.reset_mock()
|
||||
assert obj.notify(
|
||||
body='body', title='title', notify_type=NotifyType.INFO,
|
||||
attach=attach) is True
|
||||
assert mock_post.call_count == 1
|
||||
|
Loading…
Reference in New Issue
Block a user