From 8049e9e10bb7a62149fa1af240718ceba872c4ee Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Thu, 25 Feb 2016 18:04:07 +0000 Subject: [PATCH 01/21] Changed Python version number --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 4f292767..f461e74c 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,7 @@ Matrix Client SDK for Python :target: https://pypi.python.org/pypi/matrix-client/ :alt: Latest Version -This is a Matrix client-server SDK for Python 2.x. +This is a Matrix client-server SDK for Python 3.x. Usage ===== From 9f86925cb7a91c1a7e9414d82ff4d148bbdbf563 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Sun, 28 Feb 2016 15:17:41 +0000 Subject: [PATCH 02/21] Added samples with testing script --- samples/startSample.sh | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100755 samples/startSample.sh diff --git a/samples/startSample.sh b/samples/startSample.sh new file mode 100755 index 00000000..ac3f89a0 --- /dev/null +++ b/samples/startSample.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +# Will run a sample without requiring an install of the library. +PYTHONPATH="$(dirname $( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ))" +export PYTHONPATH=$PYTHONPATH +python "$@" From 6a9c54fe13bf787c0b8c269788e6c8f48a12ebc9 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Sun, 28 Feb 2016 15:59:41 +0000 Subject: [PATCH 03/21] Updated api/client to better support python3. Added media upload functions. --- matrix_client/api.py | 44 +++++++++++++++++++++++++++++++++++------ matrix_client/client.py | 14 ++++++++++++- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/matrix_client/api.py b/matrix_client/api.py index 7593662e..43976ff7 100644 --- a/matrix_client/api.py +++ b/matrix_client/api.py @@ -130,7 +130,7 @@ def join_room(self, room_id_or_alias): if not room_id_or_alias: raise MatrixError("No alias or room ID to join.") - path = "/join/%s" % urllib.quote(room_id_or_alias) + path = "/join/%s" % urlparse.quote(room_id_or_alias) return self._send("POST", path) @@ -159,10 +159,10 @@ def send_state_event(self, room_id, event_type, content, state_key=""): state_key(str): Optional. The state key for the event. """ path = ("/rooms/%s/state/%s" % - (urllib.quote(room_id), urllib.quote(event_type)) + (urlparse.quote(room_id), urlparse.quote(event_type)) ) if state_key: - path += "/%s" % (urllib.quote(state_key)) + path += "/%s" % (urlparse.quote(state_key)) return self._send("PUT", path, content) def send_message_event(self, room_id, event_type, content, txn_id=None): @@ -180,11 +180,25 @@ def send_message_event(self, room_id, event_type, content, txn_id=None): self.txn_id = self.txn_id + 1 path = ("/rooms/%s/send/%s/%s" % - (urllib.quote(room_id), urllib.quote(event_type), - urllib.quote(unicode(txn_id))) + (urlparse.quote(room_id), urlparse.quote(event_type), + urlparse.quote(str(txn_id))) ) return self._send("PUT", path, content) + # content_type can be a image,audio or video + # extra information should be supplied, see https://matrix.org/docs/spec/r0.0.1/client_server.html + def send_content(self,room_id, item_url,item_name,item_type,extra_information=None): + if extra_information == None: + extra_information = {}f + + content_pack = { + "url":item_url, + "msgtype":"m."+item_type, + "body":item_name, + "info":extra_information + } + return self.send_message_event(room_id,"m.room.message",content_pack) + def send_message(self, room_id, text_content, msgtype="m.text"): """Perform /rooms/$room_id/send/m.room.message @@ -302,7 +316,7 @@ def get_emote_body(self, text): "body": text } - def _send(self, method, path, content=None, query_params={}, headers={}): + def _send(self, method, path, content=None, query_params={}, headers={},content_type="application/json"): method = method.upper() if method not in ["GET", "PUT", "DELETE", "POST"]: raise MatrixError("Unsupported HTTP method: %s" % method) @@ -323,3 +337,21 @@ def _send(self, method, path, content=None, query_params={}, headers={}): ) return response.json() + + def media_upload(self,content,content_type): + query_params = {"access_token":self.token} + headers = {"Content-Type":content_type} + endpoint = self.url.replace( "/_matrix/client/api/v1","/_matrix/media/r0/upload") + + response = requests.request( + "POST", endpoint, params=query_params, + data=content, headers=headers + , verify=self.validate_cert #if you want to use SSL without verifying the Cert + ) + + if response.status_code < 200 or response.status_code >= 300: + raise MatrixRequestError( + code=response.status_code, content=response.text + ) + + return response.json() diff --git a/matrix_client/client.py b/matrix_client/client.py index ea89dc6c..39e95ed2 100644 --- a/matrix_client/client.py +++ b/matrix_client/client.py @@ -127,6 +127,10 @@ def start_listener_thread(self, timeout=30000): e = sys.exc_info()[0] print("Error: unable to start thread. " + str(e)) + def upload(self,content,content_type): + response = self.api.media_upload(content,content_type)["content_uri"] + return response + def _mkroom(self, room_id): self.rooms[room_id] = Room(self, room_id) return self.rooms[room_id] @@ -171,6 +175,15 @@ def send_text(self, text): def send_emote(self, text): return self.client.api.send_emote(self.room_id, text) + def send_image(self,url,name,size,mimetype,width=500,height=500): + extra_info = { + 'size':size, + 'mimetype':mimetype, + 'width':width, + 'height':height + } + return self.client.api.send_content(self.room_id, url,name,"image",extra_info) + def add_listener(self, callback): self.listeners.append(callback) @@ -256,4 +269,3 @@ def update_aliases(self): return False except MatrixRequestError: return False - From 0208fb5480fef23043afbb54a0e1dce9bb58fdb9 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Sun, 28 Feb 2016 16:00:55 +0000 Subject: [PATCH 04/21] Added simple example for writing a client. --- samples/SimpleChatClient.py | 72 +++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100755 samples/SimpleChatClient.py diff --git a/samples/SimpleChatClient.py b/samples/SimpleChatClient.py new file mode 100755 index 00000000..5708c846 --- /dev/null +++ b/samples/SimpleChatClient.py @@ -0,0 +1,72 @@ +#!/bin/env python3 +from matrix_client.client import MatrixClient +from matrix_client.api import MatrixRequestError +from requests.exceptions import MissingSchema +import sys + +def on_message(event): + if event['type'] == "m.room.member": + if event['membership'] == "join": + print("{0} joined".format(event['content']['displayname'])) + elif event['type'] == "m.room.message": + if event['content']['msgtype'] == "m.text": + print("{0}: {1}".format(event['sender'],event['content']['body'])) + else: + print(event['type']) + +host = ""; +username = ""; +room = ""; + +if len(sys.argv) > 1: + host = sys.argv[1] +else: + host = input("Host (ex: http://localhost:8008 ): ") + +client = MatrixClient(host) + +if len(sys.argv) > 2: + username = sys.argv[2] +else: + username = input("Username: ") + +password = input("Password: ") + +try: + client.login_with_password(username,password) +except MatrixRequestError as e: + if e.code == 403: + print("Bad username or password.") + else: + print("Check your sever details are correct.") + sys.exit(e.code) +except MissingSchema: + print("Bad URL format.") + sys.exit(1) + +room = None +if len(sys.argv) > 3: + room = sys.argv[3] +else: + room = input("Room ID/Alias: ") + +try: + room = client.join_room(room) +except MatrixRequestError as e: + if e.code == 400: + print("Room ID/Alias in the wrong format") + else: + print("Couldn't find room.") + sys.exit(2) + +room.add_listener(on_message) +client.start_listener_thread() + + +shouldRun = True +while shouldRun: + msg = input() + if msg == "/quit": + shouldRun = False + else: + room.send_text(msg) From d991fc4b6259edd0790450632a121316d28673b5 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Sun, 28 Feb 2016 16:01:10 +0000 Subject: [PATCH 05/21] Added help text for script. --- samples/startSample.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/samples/startSample.sh b/samples/startSample.sh index ac3f89a0..f1943134 100755 --- a/samples/startSample.sh +++ b/samples/startSample.sh @@ -1,5 +1,10 @@ #!/bin/sh +if [ "$1" == "-h" ] || [ $# -ne 1 ]; then + echo "Usage: `basename $0` scriptname [OPTIONS] " + exit 0 +fi + # Will run a sample without requiring an install of the library. PYTHONPATH="$(dirname $( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ))" export PYTHONPATH=$PYTHONPATH From 6a14f9d316ad906f5ca82520d64b9cea1da9bf0e Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Sun, 28 Feb 2016 16:11:30 +0000 Subject: [PATCH 06/21] Hide inputted password. --- samples/SimpleChatClient.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/SimpleChatClient.py b/samples/SimpleChatClient.py index 5708c846..42979f5f 100755 --- a/samples/SimpleChatClient.py +++ b/samples/SimpleChatClient.py @@ -2,6 +2,9 @@ from matrix_client.client import MatrixClient from matrix_client.api import MatrixRequestError from requests.exceptions import MissingSchema + +from getpass import getpass + import sys def on_message(event): @@ -30,7 +33,7 @@ def on_message(event): else: username = input("Username: ") -password = input("Password: ") +password = getpass() #Hide user input try: client.login_with_password(username,password) From d8805ddb69323d0983226405557da99b7321b82f Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Sun, 28 Feb 2016 16:11:59 +0000 Subject: [PATCH 07/21] Stray f --- matrix_client/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix_client/api.py b/matrix_client/api.py index 43976ff7..882f45af 100644 --- a/matrix_client/api.py +++ b/matrix_client/api.py @@ -189,7 +189,7 @@ def send_message_event(self, room_id, event_type, content, txn_id=None): # extra information should be supplied, see https://matrix.org/docs/spec/r0.0.1/client_server.html def send_content(self,room_id, item_url,item_name,item_type,extra_information=None): if extra_information == None: - extra_information = {}f + extra_information = {} content_pack = { "url":item_url, From b26083031c4c79e7fd693eb5f143a6ace10256d9 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Sun, 28 Feb 2016 16:12:10 +0000 Subject: [PATCH 08/21] Minor fixes to help in startSample.sh --- samples/startSample.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/startSample.sh b/samples/startSample.sh index f1943134..78721f8d 100755 --- a/samples/startSample.sh +++ b/samples/startSample.sh @@ -1,6 +1,6 @@ #!/bin/sh -if [ "$1" == "-h" ] || [ $# -ne 1 ]; then +if [ "$1" == "-h" ] || [ $# -lt 1 ]; then echo "Usage: `basename $0` scriptname [OPTIONS] " exit 0 fi From 39bae506549f59b18c69efb93b89a770e99ef71f Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Tue, 8 Mar 2016 22:02:54 +0000 Subject: [PATCH 09/21] Updated api.py to properly support both versions of python. --- matrix_client/api.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/matrix_client/api.py b/matrix_client/api.py index 882f45af..48b7b2b3 100644 --- a/matrix_client/api.py +++ b/matrix_client/api.py @@ -16,10 +16,12 @@ import json import re import requests -import urllib + try: import urlparse + from urllib import quote except ImportError: + from urllib.parse import quote import urllib.parse as urlparse # For python 3 class MatrixError(Exception): @@ -130,7 +132,7 @@ def join_room(self, room_id_or_alias): if not room_id_or_alias: raise MatrixError("No alias or room ID to join.") - path = "/join/%s" % urlparse.quote(room_id_or_alias) + path = "/join/%s" % quote(room_id_or_alias) return self._send("POST", path) @@ -162,7 +164,7 @@ def send_state_event(self, room_id, event_type, content, state_key=""): (urlparse.quote(room_id), urlparse.quote(event_type)) ) if state_key: - path += "/%s" % (urlparse.quote(state_key)) + path += "/%s" % (quote(state_key)) return self._send("PUT", path, content) def send_message_event(self, room_id, event_type, content, txn_id=None): @@ -180,8 +182,7 @@ def send_message_event(self, room_id, event_type, content, txn_id=None): self.txn_id = self.txn_id + 1 path = ("/rooms/%s/send/%s/%s" % - (urlparse.quote(room_id), urlparse.quote(event_type), - urlparse.quote(str(txn_id))) + (quote(room_id), quote(event_type), quote(str(txn_id))) ) return self._send("PUT", path, content) From 6d05f724b2eba5ed059a65c046b02f6a8b27a0a0 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Tue, 8 Mar 2016 22:16:14 +0000 Subject: [PATCH 10/21] Modified readme to include both python versions and sample information --- README.rst | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index f461e74c..9a84a05f 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,7 @@ Matrix Client SDK for Python :target: https://pypi.python.org/pypi/matrix-client/ :alt: Latest Version -This is a Matrix client-server SDK for Python 3.x. +This is a Matrix client-server SDK for Python 2.x and 3.x. Usage ===== @@ -49,3 +49,12 @@ transaction ID (``txn_id``) which will be incremented for each request. Client ------ This encapsulates the API module and provides object models such as ``Room``. + +Samples +======= +A collection of samples are included, written in Python 3. + +To start a sample without having to install the sdk run: + + startSample.sh samplefilename.py + From 7243ed9ed8b3cbc599db2ec7619752bd7e9b91e6 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Wed, 16 Mar 2016 11:33:59 +0000 Subject: [PATCH 11/21] Fixed script not running correctly. --- samples/startSample.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/startSample.sh b/samples/startSample.sh index 78721f8d..3cb80541 100755 --- a/samples/startSample.sh +++ b/samples/startSample.sh @@ -1,6 +1,6 @@ -#!/bin/sh +#!/bin/bash -if [ "$1" == "-h" ] || [ $# -lt 1 ]; then +if [ "$1" = "-h" ] || [ $# -lt 1 ]; then echo "Usage: `basename $0` scriptname [OPTIONS] " exit 0 fi From dc789c4604b05e26e58d682428dbbe6c70330b01 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Wed, 16 Mar 2016 13:45:28 +0000 Subject: [PATCH 12/21] Added args listing, error codes and more verbose error output. --- samples/SimpleChatClient.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/samples/SimpleChatClient.py b/samples/SimpleChatClient.py index 42979f5f..c234feb3 100755 --- a/samples/SimpleChatClient.py +++ b/samples/SimpleChatClient.py @@ -1,4 +1,16 @@ -#!/bin/env python3 +#!/usr/bin/env python3 + +# A simple chat client for matrix. +# This sample will allow you to connect to a room, and send/recieve messages. +# Args: host:port username room +# Error Codes: +# 1 - Unknown problem has occured +# 2 - Could not find the server. +# 3 - Bad URL Format. +# 4 - Bad username/password. +# 11 - Wrong room format. +# 12 - Couldn't find room. + from matrix_client.client import MatrixClient from matrix_client.api import MatrixRequestError from requests.exceptions import MissingSchema @@ -7,6 +19,7 @@ import sys +# Called when a message is recieved. def on_message(event): if event['type'] == "m.room.member": if event['membership'] == "join": @@ -40,14 +53,20 @@ def on_message(event): except MatrixRequestError as e: if e.code == 403: print("Bad username or password.") + sys.exit(4) else: print("Check your sever details are correct.") - sys.exit(e.code) -except MissingSchema: + sys.exit(3) + print(e) + +except MissingSchema as e: print("Bad URL format.") - sys.exit(1) + print(e) + sys.exit(2) + room = None + if len(sys.argv) > 3: room = sys.argv[3] else: @@ -58,9 +77,10 @@ def on_message(event): except MatrixRequestError as e: if e.code == 400: print("Room ID/Alias in the wrong format") + sys.exit(11) else: print("Couldn't find room.") - sys.exit(2) + sys.exit(12) room.add_listener(on_message) client.start_listener_thread() From 0803636492143f29ed2592c3c091d87be0971428 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Wed, 16 Mar 2016 13:45:58 +0000 Subject: [PATCH 13/21] Neatened up the code and made _send more flexible. --- matrix_client/api.py | 41 ++++++++++++++--------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/matrix_client/api.py b/matrix_client/api.py index 48b7b2b3..2cea65db 100644 --- a/matrix_client/api.py +++ b/matrix_client/api.py @@ -56,10 +56,7 @@ def __init__(self, base_url, token=None): base_url(str): The home server URL e.g. 'http://localhost:8008' token(str): Optional. The client's access token. """ - if not base_url.endswith("/_matrix/client/api/v1"): - self.url = urlparse.urljoin(base_url, "/_matrix/client/api/v1") - else: - self.url = base_url + self.base_url = base_url self.token = token self.txn_id = 0 self.validate_cert = True @@ -188,7 +185,7 @@ def send_message_event(self, room_id, event_type, content, txn_id=None): # content_type can be a image,audio or video # extra information should be supplied, see https://matrix.org/docs/spec/r0.0.1/client_server.html - def send_content(self,room_id, item_url,item_name,item_type,extra_information=None): + def send_content(self, room_id, item_url, item_name, item_type, extra_information=None): if extra_information == None: extra_information = {} @@ -198,7 +195,7 @@ def send_content(self,room_id, item_url,item_name,item_type,extra_information=No "body":item_name, "info":extra_information } - return self.send_message_event(room_id,"m.room.message",content_pack) + return self.send_message_event(room_id, "m.room.message", content_pack) def send_message(self, room_id, text_content, msgtype="m.text"): """Perform /rooms/$room_id/send/m.room.message @@ -317,35 +314,22 @@ def get_emote_body(self, text): "body": text } - def _send(self, method, path, content=None, query_params={}, headers={},content_type="application/json"): + def _send(self, method, path, content=None, query_params={}, headers={}, apipath="/_matrix/client/api/v1"): method = method.upper() if method not in ["GET", "PUT", "DELETE", "POST"]: raise MatrixError("Unsupported HTTP method: %s" % method) - headers["Content-Type"] = "application/json" - query_params["access_token"] = self.token - endpoint = self.url + path - - response = requests.request( - method, endpoint, params=query_params, - data=json.dumps(content), headers=headers - , verify=self.validate_cert #if you want to use SSL without verifying the Cert - ) + if "Content-Type" not in headers: + headers["Content-Type"] = "application/json" - if response.status_code < 200 or response.status_code >= 300: - raise MatrixRequestError( - code=response.status_code, content=response.text - ) - - return response.json() + query_params["access_token"] = self.token + endpoint = self.base_url + apipath + path - def media_upload(self,content,content_type): - query_params = {"access_token":self.token} - headers = {"Content-Type":content_type} - endpoint = self.url.replace( "/_matrix/client/api/v1","/_matrix/media/r0/upload") + if headers["Content-Type"] == "application/json": + content = json.dumps(content) response = requests.request( - "POST", endpoint, params=query_params, + method, endpoint, params=query_params, data=content, headers=headers , verify=self.validate_cert #if you want to use SSL without verifying the Cert ) @@ -356,3 +340,6 @@ def media_upload(self,content,content_type): ) return response.json() + + def media_upload(self, content, content_type): + return _send("PUT","",content=content,headers={"Content-Type":content_type},apipath="/_matrix/media/r0/upload") From 96722334c3ccedc69a3811f255b616c43d589fb5 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Wed, 16 Mar 2016 13:51:54 +0000 Subject: [PATCH 14/21] Removed several args from send_image and used kvargs instead. --- matrix_client/client.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/matrix_client/client.py b/matrix_client/client.py index 39e95ed2..79643f3c 100644 --- a/matrix_client/client.py +++ b/matrix_client/client.py @@ -128,8 +128,8 @@ def start_listener_thread(self, timeout=30000): print("Error: unable to start thread. " + str(e)) def upload(self,content,content_type): - response = self.api.media_upload(content,content_type)["content_uri"] - return response + response = self.api.media_upload(content,content_type) + return response["content_uri"] def _mkroom(self, room_id): self.rooms[room_id] = Room(self, room_id) @@ -175,14 +175,9 @@ def send_text(self, text): def send_emote(self, text): return self.client.api.send_emote(self.room_id, text) - def send_image(self,url,name,size,mimetype,width=500,height=500): - extra_info = { - 'size':size, - 'mimetype':mimetype, - 'width':width, - 'height':height - } - return self.client.api.send_content(self.room_id, url,name,"image",extra_info) + #See http://matrix.org/docs/spec/r0.0.1/client_server.html#m-image for the imageinfo args. + def send_image(self,url,name,**imageinfo): + return self.client.api.send_content(self.room_id, url,name,"image",imageinfo) def add_listener(self, callback): self.listeners.append(callback) From d90a3b1160d919481de209bac10f1bf09ef2fde4 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Wed, 16 Mar 2016 13:54:01 +0000 Subject: [PATCH 15/21] Removed redundant shouldRun --- samples/SimpleChatClient.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/samples/SimpleChatClient.py b/samples/SimpleChatClient.py index c234feb3..b27b5368 100755 --- a/samples/SimpleChatClient.py +++ b/samples/SimpleChatClient.py @@ -85,11 +85,9 @@ def on_message(event): room.add_listener(on_message) client.start_listener_thread() - -shouldRun = True -while shouldRun: +while True: msg = input() if msg == "/quit": - shouldRun = False + break else: room.send_text(msg) From 12e15b3556f972a1219a3b760974b8b99701a73e Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Wed, 16 Mar 2016 13:56:26 +0000 Subject: [PATCH 16/21] Removed shell script in favor of finding the library path inside the sample. --- samples/SimpleChatClient.py | 5 +++-- samples/startSample.sh | 11 ----------- 2 files changed, 3 insertions(+), 13 deletions(-) delete mode 100755 samples/startSample.sh diff --git a/samples/SimpleChatClient.py b/samples/SimpleChatClient.py index b27b5368..6097dc06 100755 --- a/samples/SimpleChatClient.py +++ b/samples/SimpleChatClient.py @@ -11,14 +11,15 @@ # 11 - Wrong room format. # 12 - Couldn't find room. +import sys +sys.path.insert(0, "../") # add ../ to PYTHONPATH + from matrix_client.client import MatrixClient from matrix_client.api import MatrixRequestError from requests.exceptions import MissingSchema from getpass import getpass -import sys - # Called when a message is recieved. def on_message(event): if event['type'] == "m.room.member": diff --git a/samples/startSample.sh b/samples/startSample.sh deleted file mode 100755 index 3cb80541..00000000 --- a/samples/startSample.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -if [ "$1" = "-h" ] || [ $# -lt 1 ]; then - echo "Usage: `basename $0` scriptname [OPTIONS] " - exit 0 -fi - -# Will run a sample without requiring an install of the library. -PYTHONPATH="$(dirname $( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ))" -export PYTHONPATH=$PYTHONPATH -python "$@" From 780ebff58788d2b7af1ca39d5afa48c7986f8b96 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Fri, 18 Mar 2016 15:47:59 +0000 Subject: [PATCH 17/21] Fixed sys.exit being called too soon. --- samples/SimpleChatClient.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/samples/SimpleChatClient.py b/samples/SimpleChatClient.py index 6097dc06..2a27f21e 100755 --- a/samples/SimpleChatClient.py +++ b/samples/SimpleChatClient.py @@ -52,13 +52,13 @@ def on_message(event): try: client.login_with_password(username,password) except MatrixRequestError as e: + print(e) if e.code == 403: print("Bad username or password.") sys.exit(4) else: print("Check your sever details are correct.") sys.exit(3) - print(e) except MissingSchema as e: print("Bad URL format.") @@ -76,6 +76,7 @@ def on_message(event): try: room = client.join_room(room) except MatrixRequestError as e: + print(e) if e.code == 400: print("Room ID/Alias in the wrong format") sys.exit(11) From 4b0dafe0761e09fe3d6798dde969a778945454fb Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Fri, 18 Mar 2016 16:14:17 +0000 Subject: [PATCH 18/21] Rogue Semicolons --- samples/SimpleChatClient.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/SimpleChatClient.py b/samples/SimpleChatClient.py index 2a27f21e..e75eee55 100755 --- a/samples/SimpleChatClient.py +++ b/samples/SimpleChatClient.py @@ -31,9 +31,9 @@ def on_message(event): else: print(event['type']) -host = ""; -username = ""; -room = ""; +host = "" +username = "" +room = "" if len(sys.argv) > 1: host = sys.argv[1] From 17622f8fe893b865f89046d7023bcd69fcf01c1e Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Fri, 18 Mar 2016 16:14:52 +0000 Subject: [PATCH 19/21] Descriptive error message on upload failure. --- matrix_client/client.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/matrix_client/client.py b/matrix_client/client.py index 79643f3c..021c50eb 100644 --- a/matrix_client/client.py +++ b/matrix_client/client.py @@ -12,7 +12,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from .api import MatrixHttpApi, MatrixRequestError +from .api import MatrixHttpApi, MatrixRequestError, MatrixUnexpectedResponse from threading import Thread import sys # TODO: Finish implementing this. @@ -128,8 +128,14 @@ def start_listener_thread(self, timeout=30000): print("Error: unable to start thread. " + str(e)) def upload(self,content,content_type): - response = self.api.media_upload(content,content_type) - return response["content_uri"] + try: + response = self.api.media_upload(content,content_type) + return response["content_uri"] + except MatrixRequestError as e: + raise MatrixRequestError(code=e.code, content="Upload failed: %s" % e) + except KeyError: + raise MatrixUnexpectedResponse(content="The upload was successful, but content_uri was found in response.") + def _mkroom(self, room_id): self.rooms[room_id] = Room(self, room_id) @@ -176,8 +182,8 @@ def send_emote(self, text): return self.client.api.send_emote(self.room_id, text) #See http://matrix.org/docs/spec/r0.0.1/client_server.html#m-image for the imageinfo args. - def send_image(self,url,name,**imageinfo): - return self.client.api.send_content(self.room_id, url,name,"image",imageinfo) + def send_image(self, url, name, **imageinfo): + return self.client.api.send_content(self.room_id, url, name, "image", imageinfo) def add_listener(self, callback): self.listeners.append(callback) From 8cb251c9ee04b76e0bb3b5fec8fea98e110ed0d8 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Fri, 18 Mar 2016 16:15:49 +0000 Subject: [PATCH 20/21] Misc fixes. --- matrix_client/api.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/matrix_client/api.py b/matrix_client/api.py index 2cea65db..6bc4b2af 100644 --- a/matrix_client/api.py +++ b/matrix_client/api.py @@ -28,6 +28,12 @@ class MatrixError(Exception): """A generic Matrix error. Specific errors will subclass this.""" pass +class MatrixUnexpectedResponse(MatrixError): + """The home server gave an unexpected response. """ + def __init__(self,content=""): + super(MatrixRequestError, self).__init__(content) + self.content = content + class MatrixRequestError(MatrixError): """ The home server returned an error response. """ @@ -185,13 +191,13 @@ def send_message_event(self, room_id, event_type, content, txn_id=None): # content_type can be a image,audio or video # extra information should be supplied, see https://matrix.org/docs/spec/r0.0.1/client_server.html - def send_content(self, room_id, item_url, item_name, item_type, extra_information=None): + def send_content(self, room_id, item_url, item_name, msg_type, extra_information=None): if extra_information == None: extra_information = {} content_pack = { "url":item_url, - "msgtype":"m."+item_type, + "msgtype":msg_type, "body":item_name, "info":extra_information } @@ -314,7 +320,7 @@ def get_emote_body(self, text): "body": text } - def _send(self, method, path, content=None, query_params={}, headers={}, apipath="/_matrix/client/api/v1"): + def _send(self, method, path, content=None, query_params={}, headers={}, api_path="/_matrix/client/api/v1"): method = method.upper() if method not in ["GET", "PUT", "DELETE", "POST"]: raise MatrixError("Unsupported HTTP method: %s" % method) @@ -323,7 +329,7 @@ def _send(self, method, path, content=None, query_params={}, headers={}, apipath headers["Content-Type"] = "application/json" query_params["access_token"] = self.token - endpoint = self.base_url + apipath + path + endpoint = self.base_url + api_path + path if headers["Content-Type"] == "application/json": content = json.dumps(content) From e150667fd8a4959cce380b58f9b252a4ca19e354 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Fri, 18 Mar 2016 16:16:00 +0000 Subject: [PATCH 21/21] Changed sample information on readme. --- README.rst | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/README.rst b/README.rst index 9a84a05f..e8a9c9d2 100644 --- a/README.rst +++ b/README.rst @@ -42,19 +42,15 @@ The SDK is split into two modules: ``api`` and ``client``. API --- -This contains the raw HTTP API calls and has minimal business logic. You can -set the access token (``token``) to use for requests as well as set a custom +This contains the raw HTTP API calls and has minimal business logic. You can +set the access token (``token``) to use for requests as well as set a custom transaction ID (``txn_id``) which will be incremented for each request. Client ------ -This encapsulates the API module and provides object models such as ``Room``. +This encapsulates the API module and provides object models such as ``Room``. Samples ======= A collection of samples are included, written in Python 3. - -To start a sample without having to install the sdk run: - - startSample.sh samplefilename.py - +You do not need to install matrix_client to run the samples, they will automatically include the files.