diff --git a/matrix_client/api.py b/matrix_client/api.py index 718332fc..8f9e606f 100644 --- a/matrix_client/api.py +++ b/matrix_client/api.py @@ -682,7 +682,7 @@ def create_filter(self, user_id, filter_params): filter_params) def _send(self, method, path, content=None, query_params=None, headers=None, - api_path=MATRIX_V2_API_PATH): + api_path=MATRIX_V2_API_PATH, return_json=True): if query_params is None: query_params = {} if headers is None: @@ -741,8 +741,10 @@ def _send(self, method, path, content=None, query_params=None, headers=None, raise MatrixRequestError( code=response.status_code, content=response.text ) - - return response.json() + if return_json: + return response.json() + else: + return response def media_upload(self, content, content_type): return self._send( @@ -774,8 +776,87 @@ def get_download_url(self, mxcurl): else: raise ValueError("MXC URL did not begin with 'mxc://'") + def media_download(self, mxcurl, allow_remote=True): + """Download raw media from provided mxc URL. + + Args: + mxcurl (str): mxc media URL. + allow_remote (bool): indicates to the server that it should not + attempt to fetch the media if it is deemed remote. Defaults + to true if not provided. + """ + query_params = {} + if not allow_remote: + query_params["allow_remote"] = False + if mxcurl.startswith('mxc://'): + return self._send( + "GET", mxcurl[6:], + api_path="/_matrix/media/r0/download/", + query_params=query_params, + return_json=False + ) + else: + raise ValueError( + "MXC URL '%s' did not begin with 'mxc://'" % mxcurl + ) + + def get_thumbnail(self, mxcurl, width, height, method='scale', allow_remote=True): + """Download raw media thumbnail from provided mxc URL. + + Args: + mxcurl (str): mxc media URL + width (int): desired thumbnail width + height (int): desired thumbnail height + method (str): thumb creation method. Must be + in ['scale', 'crop']. Default 'scale'. + allow_remote (bool): indicates to the server that it should not + attempt to fetch the media if it is deemed remote. Defaults + to true if not provided. + """ + if method not in ['scale', 'crop']: + raise ValueError( + "Unsupported thumb method '%s'" % method + ) + query_params = { + "width": width, + "height": height, + "method": method + } + if not allow_remote: + query_params["allow_remote"] = False + if mxcurl.startswith('mxc://'): + return self._send( + "GET", mxcurl[6:], + query_params=query_params, + api_path="/_matrix/media/r0/thumbnail/", + return_json=False + ) + else: + raise ValueError( + "MXC URL '%s' did not begin with 'mxc://'" % mxcurl + ) + + def get_url_preview(self, url, ts=None): + """Get preview for URL. + + Args: + url (str): URL to get a preview + ts (double): The preferred point in time to return + a preview for. The server may return a newer + version if it does not have the requested + version available. + """ + params = {'url': url} + if ts: + params['ts'] = ts + return self._send( + "GET", "", + query_params=params, + api_path="/_matrix/media/r0/preview_url" + ) + def get_room_id(self, room_alias): - """Get room id from its alias + """Get room id from its alias. Args: room_alias (str): The room alias name. diff --git a/test/api_test.py b/test/api_test.py index effc2cef..90175918 100644 --- a/test/api_test.py +++ b/test/api_test.py @@ -1,10 +1,11 @@ import responses import pytest import json +from copy import deepcopy from matrix_client import client, api from matrix_client.errors import MatrixRequestError, MatrixError, MatrixHttpLibError from matrix_client import __version__ as lib_version - +from . import response_examples MATRIX_V2_API_PATH = "/_matrix/client/r0" @@ -317,6 +318,72 @@ def test_send_request_error(self): mapi._send("GET", self.test_path) +class TestMediaApi: + cli = client.MatrixClient("http://example.com") + user_id = "@alice:example.com" + mxcurl = "mxc://example.com/OonjUOmcuVpUnmOWKtzPmAFe" + + @responses.activate + def test_media_download(self): + media_url = \ + "http://example.com/_matrix/media/r0/download/" + self.mxcurl[6:] + with open('test/response_examples.py', 'rb') as fil: + responses.add( + responses.GET, media_url, + content_type='application/python', + body=fil.read(), status=200, stream=True + ) + resp = self.cli.api.media_download(self.mxcurl, allow_remote=False) + resp.raw.decode_content = True + req = responses.calls[0].request + assert req.url.split('?')[0] == media_url + assert req.method == 'GET' + + def test_media_download_wrong_url(self): + with pytest.raises(ValueError): + self.cli.api.media_download(self.mxcurl[6:]) + + @responses.activate + def test_get_thumbnail(self): + media_url = \ + "http://example.com/_matrix/media/r0/thumbnail/" + self.mxcurl[6:] + with open('test/response_examples.py', 'rb') as fil: + responses.add( + responses.GET, media_url, + content_type='application/python', + body=fil.read(), status=200, stream=True + ) + resp = self.cli.api.get_thumbnail( + self.mxcurl, 28, 28, allow_remote=False + ) + resp.raw.decode_content = True + req = responses.calls[0].request + assert req.url.split('?')[0] == media_url + assert req.method == 'GET' + + def test_get_thumbnail_wrong_url(self): + with pytest.raises(ValueError): + self.cli.api.get_thumbnail(self.mxcurl[6:], 28, 28) + + def test_get_thumbnail_wrong_method(self): + with pytest.raises(ValueError): + self.cli.api.get_thumbnail(self.mxcurl, 28, 28, 'cut') + + @responses.activate + def test_get_url_preview(self): + media_url = \ + "http://example.com/_matrix/media/r0/preview_url" + preview_url = deepcopy(response_examples.example_preview_url) + responses.add( + responses.GET, media_url, + body=json.dumps(preview_url) + ) + self.cli.api.get_url_preview("https://google.com/", 1510610716656) + req = responses.calls[0].request + assert req.url.split('?')[0] == media_url + assert req.method == 'GET' + + class TestRoomApi: cli = client.MatrixClient("http://example.com") user_id = "@user:matrix.org" diff --git a/test/response_examples.py b/test/response_examples.py index 7e4787bb..2d45aa86 100644 --- a/test/response_examples.py +++ b/test/response_examples.py @@ -174,3 +174,13 @@ "home_server": "matrix.org", "device_id": "GHTYAJCE" } + +example_preview_url = { + "matrix:image:size": 102400, + "og:description": "This is a really cool blog post from matrix.org", + "og:image": "mxc://example.com/ascERGshawAWawugaAcauga", + "og:image:height": 48, + "og:image:type": "image/png", + "og:image:width": 48, + "og:title": "Matrix Blog Post" +}