mirror of https://github.com/caronc/apprise
Fix Matrix v3 attachments (#1373)
parent
8929358803
commit
f65f99cd5b
|
@ -81,6 +81,9 @@ IS_ROOM_ID = re.compile(
|
||||||
re.I,
|
re.I,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Matrix is_image check
|
||||||
|
IS_IMAGE = re.compile(r"^image/.*", re.I)
|
||||||
|
|
||||||
|
|
||||||
class MatrixMessageType:
|
class MatrixMessageType:
|
||||||
"""The Matrix Message types."""
|
"""The Matrix Message types."""
|
||||||
|
@ -692,6 +695,9 @@ class NotifyMatrix(NotifyBase):
|
||||||
# Get our room
|
# Get our room
|
||||||
room = rooms.pop(0)
|
room = rooms.pop(0)
|
||||||
|
|
||||||
|
# Set method according to MatrixVersion
|
||||||
|
method = "PUT" if self.version == MatrixVersion.V3 else "POST"
|
||||||
|
|
||||||
# Get our room_id from our response
|
# Get our room_id from our response
|
||||||
room_id = self._room_join(room)
|
room_id = self._room_join(room)
|
||||||
if not room_id:
|
if not room_id:
|
||||||
|
@ -717,11 +723,7 @@ class NotifyMatrix(NotifyBase):
|
||||||
f"/rooms/{NotifyMatrix.quote(room_id)}/send/m.room.message"
|
f"/rooms/{NotifyMatrix.quote(room_id)}/send/m.room.message"
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.version == MatrixVersion.V2:
|
if image_url and self.version == MatrixVersion.V2:
|
||||||
#
|
|
||||||
# Attachments don't work beyond V2 at this time
|
|
||||||
#
|
|
||||||
if image_url:
|
|
||||||
# Define our payload
|
# Define our payload
|
||||||
image_payload = {
|
image_payload = {
|
||||||
"msgtype": "m.image",
|
"msgtype": "m.image",
|
||||||
|
@ -731,8 +733,7 @@ class NotifyMatrix(NotifyBase):
|
||||||
|
|
||||||
# Post our content
|
# Post our content
|
||||||
postokay, response = self._fetch(
|
postokay, response = self._fetch(
|
||||||
path, payload=image_payload
|
path, payload=image_payload)
|
||||||
)
|
|
||||||
if not postokay:
|
if not postokay:
|
||||||
# Mark our failure
|
# Mark our failure
|
||||||
has_error = True
|
has_error = True
|
||||||
|
@ -744,8 +745,21 @@ class NotifyMatrix(NotifyBase):
|
||||||
attachment["type"] = "m.room.message"
|
attachment["type"] = "m.room.message"
|
||||||
|
|
||||||
postokay, response = self._fetch(
|
postokay, response = self._fetch(
|
||||||
path, payload=attachment
|
path, payload=attachment, method=method)
|
||||||
|
|
||||||
|
# Increment the transaction ID to avoid future messages
|
||||||
|
# being recognized as retransmissions and ignored
|
||||||
|
if self.version == MatrixVersion.V3 \
|
||||||
|
and self.access_token != self.password:
|
||||||
|
self.transaction_id += 1
|
||||||
|
self.store.set(
|
||||||
|
"transaction_id", self.transaction_id,
|
||||||
|
expires=self.default_cache_expiry_sec)
|
||||||
|
path = "/rooms/{}/send/m.room.message/{}".format(
|
||||||
|
NotifyMatrix.quote(room_id),
|
||||||
|
self.transaction_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not postokay:
|
if not postokay:
|
||||||
# Mark our failure
|
# Mark our failure
|
||||||
has_error = True
|
has_error = True
|
||||||
|
@ -790,7 +804,6 @@ class NotifyMatrix(NotifyBase):
|
||||||
})
|
})
|
||||||
|
|
||||||
# Post our content
|
# Post our content
|
||||||
method = "PUT" if self.version == MatrixVersion.V3 else "POST"
|
|
||||||
postokay, response = self._fetch(
|
postokay, response = self._fetch(
|
||||||
path, payload=payload, method=method
|
path, payload=payload, method=method
|
||||||
)
|
)
|
||||||
|
@ -824,18 +837,14 @@ class NotifyMatrix(NotifyBase):
|
||||||
"""Posts all of the provided attachments."""
|
"""Posts all of the provided attachments."""
|
||||||
|
|
||||||
payloads = []
|
payloads = []
|
||||||
if self.version != MatrixVersion.V2:
|
|
||||||
self.logger.warning(
|
|
||||||
"Add ?v=2 to Apprise URL to support Attachments"
|
|
||||||
)
|
|
||||||
return next((False for a in attach if not a), [])
|
|
||||||
|
|
||||||
for attachment in attach:
|
for attachment in attach:
|
||||||
if not attachment:
|
if not attachment:
|
||||||
# invalid attachment (bad file)
|
# invalid attachment (bad file)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not re.match(r"^image/", attachment.mimetype, re.I):
|
if not IS_IMAGE.match(attachment.mimetype) \
|
||||||
|
and self.version == MatrixVersion.V2:
|
||||||
# unsuppored at this time
|
# unsuppored at this time
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -849,29 +858,23 @@ class NotifyMatrix(NotifyBase):
|
||||||
# "content_uri": "mxc://example.com/a-unique-key"
|
# "content_uri": "mxc://example.com/a-unique-key"
|
||||||
# }
|
# }
|
||||||
|
|
||||||
# FUTURE if self.version == MatrixVersion.V3:
|
if self.version == MatrixVersion.V3:
|
||||||
# FUTURE # Prepare our payload
|
# Prepare our payload
|
||||||
# FUTURE payloads.append({
|
is_image = IS_IMAGE.match(attachment.mimetype)
|
||||||
# FUTURE "body": attachment.name,
|
payloads.append({
|
||||||
# FUTURE "info": {
|
"body": attachment.name,
|
||||||
# FUTURE "mimetype": attachment.mimetype,
|
"info": {
|
||||||
# FUTURE "size": len(attachment),
|
"mimetype": attachment.mimetype,
|
||||||
# FUTURE },
|
"size": len(attachment),
|
||||||
# FUTURE "msgtype": "m.image",
|
},
|
||||||
# FUTURE "url": response.get('content_uri'),
|
"msgtype": "m.image" if is_image else "m.file",
|
||||||
# FUTURE })
|
"url": response.get("content_uri"),
|
||||||
|
})
|
||||||
# FUTURE else:
|
if not is_image:
|
||||||
# FUTURE # Prepare our payload
|
# Setup `m.file'
|
||||||
# FUTURE payloads.append({
|
payloads[-1]["filename"] = attachment.name
|
||||||
# FUTURE "info": {
|
|
||||||
# FUTURE "mimetype": attachment.mimetype,
|
|
||||||
# FUTURE },
|
|
||||||
# FUTURE "msgtype": "m.image",
|
|
||||||
# FUTURE "body": "tta.webp",
|
|
||||||
# FUTURE "url": response.get('content_uri'),
|
|
||||||
# FUTURE })
|
|
||||||
|
|
||||||
|
else:
|
||||||
# Prepare our payload
|
# Prepare our payload
|
||||||
payloads.append({
|
payloads.append({
|
||||||
"info": {
|
"info": {
|
||||||
|
@ -1335,11 +1338,10 @@ class NotifyMatrix(NotifyBase):
|
||||||
status_code = requests.codes.internal_server_error
|
status_code = requests.codes.internal_server_error
|
||||||
|
|
||||||
if path == "/upload":
|
if path == "/upload":
|
||||||
# FUTURE if self.version == MatrixVersion.V3:
|
if self.version == MatrixVersion.V3:
|
||||||
# FUTURE url += MATRIX_V3_MEDIA_PATH + path
|
url += MATRIX_V3_MEDIA_PATH + path
|
||||||
|
|
||||||
# FUTURE else:
|
else:
|
||||||
# FUTURE url += MATRIX_V2_MEDIA_PATH + path
|
|
||||||
url += MATRIX_V2_MEDIA_PATH + path
|
url += MATRIX_V2_MEDIA_PATH + path
|
||||||
|
|
||||||
params.update({"filename": attachment.name})
|
params.update({"filename": attachment.name})
|
||||||
|
|
|
@ -1002,9 +1002,8 @@ def test_plugin_matrix_image_errors(mock_post, mock_get, mock_put):
|
||||||
|
|
||||||
|
|
||||||
@mock.patch("requests.put")
|
@mock.patch("requests.put")
|
||||||
@mock.patch("requests.get")
|
|
||||||
@mock.patch("requests.post")
|
@mock.patch("requests.post")
|
||||||
def test_plugin_matrix_attachments_api_v3(mock_post, mock_get, mock_put):
|
def test_plugin_matrix_attachments_api_v3(mock_post, mock_put):
|
||||||
"""NotifyMatrix() Attachment Checks (v3)"""
|
"""NotifyMatrix() Attachment Checks (v3)"""
|
||||||
|
|
||||||
# Prepare a good response
|
# Prepare a good response
|
||||||
|
@ -1018,7 +1017,6 @@ def test_plugin_matrix_attachments_api_v3(mock_post, mock_get, mock_put):
|
||||||
|
|
||||||
# Prepare Mock return object
|
# Prepare Mock return object
|
||||||
mock_post.return_value = response
|
mock_post.return_value = response
|
||||||
mock_get.return_value = response
|
|
||||||
mock_put.return_value = response
|
mock_put.return_value = response
|
||||||
|
|
||||||
# Instantiate our object
|
# Instantiate our object
|
||||||
|
@ -1040,23 +1038,22 @@ def test_plugin_matrix_attachments_api_v3(mock_post, mock_get, mock_put):
|
||||||
attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, "apprise-test.gif"))
|
attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, "apprise-test.gif"))
|
||||||
|
|
||||||
# Test our call count
|
# Test our call count
|
||||||
assert mock_put.call_count == 1
|
assert mock_put.call_count == 2
|
||||||
assert mock_post.call_count == 2
|
assert mock_post.call_count == 3
|
||||||
assert (
|
assert mock_post.call_args_list[0][0][0] == \
|
||||||
mock_post.call_args_list[0][0][0]
|
"http://localhost/_matrix/client/v3/login"
|
||||||
== "http://localhost/_matrix/client/v3/login"
|
assert mock_post.call_args_list[1][0][0] == \
|
||||||
)
|
"http://localhost/_matrix/media/v3/upload"
|
||||||
assert (
|
assert mock_post.call_args_list[2][0][0] == \
|
||||||
mock_post.call_args_list[1][0][0]
|
"http://localhost/_matrix/client/v3/join/%23general%3Alocalhost"
|
||||||
== "http://localhost/_matrix/client/v3/join/%23general%3Alocalhost"
|
assert mock_put.call_args_list[0][0][0] == \
|
||||||
)
|
"http://localhost/_matrix/client/v3/rooms/%21abc123%3Alocalhost/" \
|
||||||
assert (
|
|
||||||
mock_put.call_args_list[0][0][0]
|
|
||||||
== "http://localhost/_matrix/client/v3/rooms/%21abc123%3Alocalhost/"
|
|
||||||
"send/m.room.message/0"
|
"send/m.room.message/0"
|
||||||
)
|
assert mock_put.call_args_list[1][0][0] == \
|
||||||
|
"http://localhost/_matrix/client/v3/rooms/%21abc123%3Alocalhost/" \
|
||||||
|
"send/m.room.message/1"
|
||||||
|
|
||||||
# Attach an unsupported file type (it's just skipped)
|
# Attach a zip file type
|
||||||
attach = AppriseAttachment(
|
attach = AppriseAttachment(
|
||||||
os.path.join(TEST_VAR_DIR, "apprise-archive.zip")
|
os.path.join(TEST_VAR_DIR, "apprise-archive.zip")
|
||||||
)
|
)
|
||||||
|
@ -1086,28 +1083,37 @@ def test_plugin_matrix_attachments_api_v3(mock_post, mock_get, mock_put):
|
||||||
# update our attachment to be valid
|
# update our attachment to be valid
|
||||||
attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, "apprise-test.gif"))
|
attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, "apprise-test.gif"))
|
||||||
|
|
||||||
|
mock_put.return_value = None
|
||||||
mock_post.return_value = None
|
mock_post.return_value = None
|
||||||
|
|
||||||
# Throw an exception on the first call to requests.post()
|
# Throw an exception on the first call to requests.post()
|
||||||
for side_effect in (requests.RequestException(), OSError(), bad_response):
|
for side_effect in (requests.RequestException(), OSError(), bad_response):
|
||||||
|
# Reset our value
|
||||||
|
mock_put.reset_mock()
|
||||||
|
mock_post.reset_mock()
|
||||||
|
|
||||||
mock_post.side_effect = [side_effect]
|
mock_post.side_effect = [side_effect]
|
||||||
|
|
||||||
# We'll never fail because files are not attached
|
assert obj.send(body="test", attach=attach) is False
|
||||||
assert obj.send(body="test", attach=attach) is True
|
|
||||||
|
|
||||||
# Throw an exception on the second call to requests.post()
|
# Throw an exception on the second call to requests.post()
|
||||||
for side_effect in (requests.RequestException(), OSError(), bad_response):
|
for side_effect in (requests.RequestException(), OSError(), bad_response):
|
||||||
mock_post.side_effect = [response, side_effect]
|
# Reset our value
|
||||||
|
mock_put.reset_mock()
|
||||||
|
mock_post.reset_mock()
|
||||||
|
|
||||||
# Attachment support does not exist vor v3 at time, so this will
|
mock_put.side_effect = [side_effect, response]
|
||||||
# work nicely
|
mock_post.side_effect = [response, side_effect, response]
|
||||||
assert obj.send(body="test", attach=attach) is True
|
|
||||||
|
# We'll fail now because of our error handling
|
||||||
|
assert obj.send(body="test", attach=attach) is False
|
||||||
|
|
||||||
# handle a bad response
|
# handle a bad response
|
||||||
|
mock_put.side_effect = [bad_response, response]
|
||||||
mock_post.side_effect = [response, bad_response, response]
|
mock_post.side_effect = [response, bad_response, response]
|
||||||
|
|
||||||
# Attachment support does not exist vor v3 at time, so this will
|
# We'll fail now because of an internal exception
|
||||||
# work nicely
|
assert obj.send(body="test", attach=attach) is False
|
||||||
assert obj.send(body="test", attach=attach) is True
|
|
||||||
|
|
||||||
# Force a object removal (thus a logout call)
|
# Force a object removal (thus a logout call)
|
||||||
del obj
|
del obj
|
||||||
|
|
Loading…
Reference in New Issue