Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • briar/python-briar-wrapper
1 result
Show changes
Commits on Source (2)
...@@ -23,8 +23,6 @@ class Api: ...@@ -23,8 +23,6 @@ class Api:
def __init__(self, headless_jar): def __init__(self, headless_jar):
self._command = ["java", "-jar", headless_jar] self._command = ["java", "-jar", headless_jar]
self.socket_listener = SocketListener(self)
@staticmethod @staticmethod
def has_account(): def has_account():
return isfile(BRIAR_DB) return isfile(BRIAR_DB)
...@@ -67,14 +65,17 @@ class Api: ...@@ -67,14 +65,17 @@ class Api:
sleep(0.1) sleep(0.1)
except HTTPError as http_error: except HTTPError as http_error:
if http_error.code == 404: if http_error.code == 404:
self._load_auth_token() return self._on_successful_startup(callback)
callback(True)
return
except URLError as url_error: except URLError as url_error:
if not isinstance(url_error.reason, ConnectionRefusedError): if not isinstance(url_error.reason, ConnectionRefusedError):
raise url_error raise url_error
callback(False) callback(False)
def _on_successful_startup(self, callback):
self._load_auth_token()
self.socket_listener = SocketListener(self)
callback(True)
def _login(self, password): def _login(self, password):
if not self.is_running(): if not self.is_running():
raise Exception("Can't login; API not running") raise Exception("Can't login; API not running")
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
# License-Filename: LICENSE.md # License-Filename: LICENSE.md
from operator import itemgetter
from urllib.parse import urljoin from urllib.parse import urljoin
from requests import get as _get from requests import get as _get
...@@ -24,18 +25,12 @@ class Contacts(Model): ...@@ -24,18 +25,12 @@ class Contacts(Model):
def get(self): def get(self):
url = urljoin(BASE_HTTP_URL, self.API_ENDPOINT) url = urljoin(BASE_HTTP_URL, self.API_ENDPOINT)
request = _get(url, headers=self._headers) request = _get(url, headers=self._headers)
return request.json() contacts = request.json()
contacts.sort(key=itemgetter("lastChatActivity"),
reverse=True)
return contacts
def get_link(self): def get_link(self):
url = urljoin(BASE_HTTP_URL, self.API_ENDPOINT + "add/" + "link/") url = urljoin(BASE_HTTP_URL, self.API_ENDPOINT + "add/" + "link/")
request = _get(url, headers=self._headers).json() request = _get(url, headers=self._headers).json()
return request['link'] return request['link']
def watch_contacts(self, callback):
self._on_contact_added_callback = callback
self._api.socket_listener.watch("ContactAddedEvent",
self._on_contact_added)
# pylint: disable=unused-argument
def _on_contact_added(self, event):
self._on_contact_added_callback()
...@@ -28,14 +28,6 @@ class PrivateChat(Model): ...@@ -28,14 +28,6 @@ class PrivateChat(Model):
request = _get(url, headers=self._headers) request = _get(url, headers=self._headers)
return request.json() return request.json()
def watch_messages(self, callback):
self._on_message_received_callback = callback
self._api.socket_listener.watch("ConversationMessageReceivedEvent",
self._on_message_received)
def _on_message_received(self, event):
self._on_message_received_callback(event['data'])
def send(self, message): def send(self, message):
url = urljoin(BASE_HTTP_URL, url = urljoin(BASE_HTTP_URL,
self.API_ENDPOINT + "/%i" % self._contact_id) self.API_ENDPOINT + "/%i" % self._contact_id)
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
import asyncio import asyncio
import json import json
from threading import Thread from threading import Thread, Lock
import websockets import websockets
...@@ -12,33 +12,55 @@ from briar_wrapper.constants import WEBSOCKET_URL ...@@ -12,33 +12,55 @@ from briar_wrapper.constants import WEBSOCKET_URL
from briar_wrapper.model import Model from briar_wrapper.model import Model
class SocketListener(Model): # pylint: disable=too-few-public-methods class SocketListener(): # pylint: disable=too-few-public-methods
def watch(self, event, callback): def __init__(self, api):
self._api = api
self._signals = list()
self._signals_lock = Lock()
self._start_websocket_thread()
def connect(self, event, callback):
self._signals_lock.acquire()
# TODO: Signal ID should be stable after disconnects
signal_id = len(self._signals)
self._signals.append({
"event": event,
"callback": callback
})
self._signals_lock.release()
return signal_id
def _start_websocket_thread(self):
websocket_thread = Thread(target=self._start_watch_loop, websocket_thread = Thread(target=self._start_watch_loop,
args=(event, callback),
daemon=True) daemon=True)
websocket_thread.start() websocket_thread.start()
def _start_watch_loop(self, event, callback): def _start_watch_loop(self):
loop = asyncio.new_event_loop() loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop) asyncio.set_event_loop(loop)
loop.create_task(self._start_websocket(event, callback)) loop.create_task(self._start_websocket())
loop.run_forever() loop.run_forever()
loop.close() loop.close()
async def _start_websocket(self, event, callback): async def _start_websocket(self):
async with websockets.connect(WEBSOCKET_URL) as websocket: async with websockets.connect(WEBSOCKET_URL) as websocket:
await websocket.send(self._api.auth_token) await websocket.send(self._api.auth_token)
await self._watch_messages(websocket, event, callback) await self._watch_messages(websocket)
async def _watch_messages(self, websocket, event, callback): async def _watch_messages(self, websocket):
while not websocket.closed and not\ while not websocket.closed and not\
asyncio.get_event_loop().is_closed(): asyncio.get_event_loop().is_closed():
message_json = await websocket.recv() message_json = await websocket.recv()
message = json.loads(message_json) message = json.loads(message_json)
if message['name'] == event: self._call_signal_callbacks(message)
callback(message)
if not asyncio.get_event_loop().is_closed(): if not asyncio.get_event_loop().is_closed():
asyncio.get_event_loop().create_task( asyncio.get_event_loop().create_task(
self._watch_messages(websocket, event, callback)) self._watch_messages(websocket))
def _call_signal_callbacks(self, message):
self._signals_lock.acquire()
for signal in self._signals:
if signal["event"] == message['name']:
signal["callback"](message)
self._signals_lock.release()