Skip to content

Commit

Permalink
added Signal Attachment Support
Browse files Browse the repository at this point in the history
  • Loading branch information
caronc committed May 1, 2022
1 parent 28cb911 commit f0cb704
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 3 deletions.
32 changes: 31 additions & 1 deletion apprise/plugins/NotifySignalAPI.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import re
import requests
from json import dumps
import base64

from .NotifyBase import NotifyBase
from ..common import NotifyType
Expand Down Expand Up @@ -210,7 +211,8 @@ def __init__(self, source=None, targets=None, batch=False, status=False,

return

def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs):
def send(self, body, title='', notify_type=NotifyType.INFO, attach=None,
**kwargs):
"""
Perform Signal API Notification
"""
Expand All @@ -224,6 +226,30 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs):
# error tracking (used for function return)
has_error = False

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:
# Prepare our Attachment in Base64
attachments.append(
base64.b64encode(f.read()).decode('utf-8'))

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 our headers
headers = {
'User-Agent': self.app_id,
Expand Down Expand Up @@ -253,6 +279,10 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs):
"recipients": []
}

if attachments:
# Store our attachments
payload['base64_attachments'] = attachments

# Determine Authentication
auth = None
if self.user:
Expand Down
3 changes: 1 addition & 2 deletions apprise/plugins/NotifyXML.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,7 @@ def send(self, body, title='', notify_type=NotifyType.INFO, attach=None,

try:
with open(attachment.path, 'rb') as f:
# Output must be in a DataURL format (that's what
# PushSafer calls it):
# Prepare our Attachment in Base64
entry = \
'<Attachment filename="{}" mimetype="{}">'.format(
NotifyXML.escape_html(
Expand Down
79 changes: 79 additions & 0 deletions test/test_plugin_signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,25 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import os
import sys
from json import loads
import mock
import pytest
import requests
from apprise import plugins
from apprise import Apprise
from helpers import AppriseURLTester
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 = (
('signal://', {
Expand Down Expand Up @@ -293,3 +300,75 @@ def test_plugin_signal_test_based_on_feedback(mock_post):
assert '/@group2' in aobj[0].url()
# Our target phone number is also in the path
assert '/+12514444444' in aobj[0].url()


@mock.patch('requests.post')
def test_notify_signal_plugin_attachments(mock_post):
"""
NotifySignalAPI() Attachments
"""
# Disable Throttling to speed testing
plugins.NotifyBase.request_rate_per_sec = 0

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(
'signal://10.0.0.112:8080/+12512222222/+12513333333/'
'12514444444?batch=no')
assert isinstance(obj, plugins.NotifySignalAPI)

# 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

# Get a appropriate "builtin" module name for pythons 2/3.
if sys.version_info.major >= 3:
builtin_open_function = 'builtins.open'

else:
builtin_open_function = '__builtin__.open'

# 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(builtin_open_function, 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(
'signal://10.0.0.112:8080/+12512222222/+12513333333/'
'12514444444?batch=yes')
assert isinstance(obj, plugins.NotifySignalAPI)

# 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

0 comments on commit f0cb704

Please sign in to comment.