diff --git a/src/briar/api/api.py b/src/briar/api/api.py index 44ad5d96c3dda43bc060a309627ea5ce18bf12cf..1a8a99aca6bbff92b136fe2005a6966c0a70c8e8 100644 --- a/src/briar/api/api.py +++ b/src/briar/api/api.py @@ -2,8 +2,10 @@ # SPDX-License-Identifier: AGPL-3.0-only # License-Filename: LICENSE.md -from briar.api.constants import Constants +from briar.api.constants import BASE_HTTP_URL, BRIAR_AUTH_TOKEN, BRIAR_DB +from briar.api.models.socket_listener import SocketListener +from os.path import isfile from subprocess import Popen, PIPE, STDOUT from threading import Thread from time import sleep @@ -14,18 +16,17 @@ from urllib.request import urlopen class Api: auth_token = None + socket_listener = None + _process = None def __init__(self, headless_jar): - self._command = ['java', '-jar', headless_jar] - self.constants = Constants() - self._load_auth_token() + self._command = ["java", "-jar", headless_jar] + + self.socket_listener = SocketListener(self) def has_account(self): - from pathlib import Path - home = str(Path.home()) - from os.path import isdir, join - return isdir(join(home, ".briar", "db")) + return isfile(BRIAR_DB) def is_running(self): return (self._process is not None) and (self._process.poll() is None) @@ -61,22 +62,22 @@ class Api: def _watch_thread(self, callback): while self.is_running(): try: + urlopen(BASE_HTTP_URL) sleep(0.1) - print(urlopen(self.constants.get_base_url()).getcode()) - except HTTPError as e: - if(e.code == 404): + except HTTPError as http_error: + if(http_error.code == 404): self._load_auth_token() callback(True) return - except URLError as e: - if not isinstance(e.reason, ConnectionRefusedError): - raise e + except URLError as url_error: + if not isinstance(url_error.reason, ConnectionRefusedError): + raise url_error callback(False) def _login(self, password): if not self.is_running(): raise Exception("Can't login; API not running") - self._process.communicate((password + '\n').encode("utf-8")) + self._process.communicate(("%s\n" % password).encode("utf-8")) def _register(self, credentials): if not self.is_running(): @@ -87,7 +88,7 @@ class Api: def _load_auth_token(self): if not self.has_account(): - return - with open(self.constants.get_auth_token(), 'r') as file: + raise Exception("Can't load authentication token") + with open(BRIAR_AUTH_TOKEN, 'r') as file: self.auth_token = file.read() diff --git a/src/briar/api/constants.py b/src/briar/api/constants.py index 10c7d9701977bce227edafb31cb7e82405f60b92..94794a1ab75650b52e0a913f695160df0529d7ce 100644 --- a/src/briar/api/constants.py +++ b/src/briar/api/constants.py @@ -6,17 +6,13 @@ from os.path import join from pathlib import Path from urllib.parse import urljoin +_BRIAR_DIR = ".briar" -class Constants: +_HOST = "%s://localhost:7000" +_VERSION_SUFFIX = "v1/" - _BRIAR_AUTH_TOKEN = 'auth_token' - _BRIAR_DIR = '.briar' +BRIAR_AUTH_TOKEN = join(Path.home(), _BRIAR_DIR, "auth_token") +BRIAR_DB = join(Path.home(), _BRIAR_DIR, "db", "db.mv.db") - _HOST = 'http://localhost:7000' - _VERSION_SUFFIX = 'v1/' - - def get_auth_token(self): - return join(Path.home(), self._BRIAR_DIR, self._BRIAR_AUTH_TOKEN) - - def get_base_url(self): - return urljoin(self._HOST, self._VERSION_SUFFIX) +BASE_HTTP_URL = urljoin(_HOST % "http", _VERSION_SUFFIX) +WEBSOCKET_URL = urljoin(_HOST % "ws", "%s/ws" % _VERSION_SUFFIX) diff --git a/src/briar/api/models/contacts.py b/src/briar/api/models/contacts.py index b80d38059c7c45236f62a8775d93b16c7d15838b..69e5524d560a15d6bf8c80606a36b3d00c8b0c5f 100644 --- a/src/briar/api/models/contacts.py +++ b/src/briar/api/models/contacts.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: AGPL-3.0-only # License-Filename: LICENSE.md +from briar.api.constants import BASE_HTTP_URL from briar.api.models.model import Model from requests import get as _get @@ -11,7 +12,6 @@ from urllib.parse import urljoin class Contacts(Model): def get(self): - headers = {'Authorization': 'Bearer ' + self._api.auth_token} - url = urljoin(self._constants.get_base_url(), 'contacts') - r = _get(url, headers=headers) + url = urljoin(BASE_HTTP_URL, 'contacts') + r = _get(url, headers=self._headers) return r.json() diff --git a/src/briar/api/models/model.py b/src/briar/api/models/model.py index 8c1c89c31978479242cf65a3d20b1a59a6b23f38..e28cb2d5a470519d8af852ea6f5731f9327dd827 100644 --- a/src/briar/api/models/model.py +++ b/src/briar/api/models/model.py @@ -5,6 +5,11 @@ class Model: + _headers = {} + def __init__(self, api): self._api = api - self._constants = api.constants + self._initialize_headers() + + def _initialize_headers(self): + self._headers['Authorization'] = 'Bearer %s' % self._api.auth_token diff --git a/src/briar/api/models/private_chat.py b/src/briar/api/models/private_chat.py index c11fadbd72e8ee0ec9b0fd7a5419819193667d90..db5a33dbf442f46bd3d8ee643603a1300e2d94ad 100644 --- a/src/briar/api/models/private_chat.py +++ b/src/briar/api/models/private_chat.py @@ -2,8 +2,8 @@ # SPDX-License-Identifier: AGPL-3.0-only # License-Filename: LICENSE.md +from briar.api.constants import BASE_HTTP_URL from briar.api.models.model import Model -from briar.api.models.socket_listener import SocketListener from requests import get as _get from requests import post as _post @@ -13,17 +13,15 @@ from urllib.parse import urljoin class PrivateChat(Model): def get(self, contact_id): - headers = {'Authorization': 'Bearer ' + self._api.auth_token} - url = urljoin(self._constants.get_base_url(), 'messages/%i' % contact_id) - r = _get(url, headers=headers) - return r.json() + url = urljoin(BASE_HTTP_URL, 'messages/%i' % contact_id) + request = _get(url, headers=self._headers) + return request.json() def watch_messages(self, contact_id, callback): - socket_listener = SocketListener(self._api) - socket_listener.watch(callback, "ConversationMessageReceivedEvent", - contact_id=contact_id) + self._api.socket_listener.watch(callback, + "ConversationMessageReceivedEvent", + contact_id=contact_id) def send(self, contact_id, message): - headers = {'Authorization': 'Bearer ' + self._api.auth_token} - url = urljoin(self._constants.get_base_url(), 'messages/%s' % contact_id) - _post(url, headers=headers, json={'text': message}) + url = urljoin(BASE_HTTP_URL, 'messages/%s' % contact_id) + _post(url, headers=self._headers, json={'text': message}) diff --git a/src/briar/api/models/socket_listener.py b/src/briar/api/models/socket_listener.py index 93646f4a75b0de4cc2fef4c5d13c853799c89a28..444ca3800ae078bc9082521108d91ab1eb6cc2a6 100644 --- a/src/briar/api/models/socket_listener.py +++ b/src/briar/api/models/socket_listener.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: AGPL-3.0-only # License-Filename: LICENSE.md +from briar.api.constants import WEBSOCKET_URL from briar.api.models.model import Model import asyncio @@ -10,6 +11,7 @@ from threading import Thread import websockets +# TODO: Make more general; currently very specific to private messages class SocketListener(Model): def watch(self, callback, event, contact_id="0"): @@ -26,16 +28,17 @@ class SocketListener(Model): loop.close() async def _start_websocket(self, callback, event, contact_id="0"): - async with websockets.connect('ws://localhost:7000/v1/ws') as websocket: + async with websockets.connect(WEBSOCKET_URL) as websocket: await websocket.send(self._api.auth_token) - await self._watch_messages(websocket, callback) + await self._watch_messages(websocket, event, callback) - async def _watch_messages(self, websocket, callback): - while not websocket.closed and not asyncio.get_event_loop().is_closed(): + async def _watch_messages(self, websocket, event, callback): + while not websocket.closed and not\ + asyncio.get_event_loop().is_closed(): message = await websocket.recv() - m = json.loads(message) - if m['name'] == 'ConversationMessageReceivedEvent': - callback(m['data']) + message = json.loads(message) + if message['name'] == event: + callback(message['data']) if not asyncio.get_event_loop().is_closed(): asyncio.get_event_loop().create_task( self._watch_messages(websocket, callback))