From d57414c06c55a5e5e54a064257f241c789fcf000 Mon Sep 17 00:00:00 2001 From: vslg Date: Thu, 16 Jul 2020 17:09:14 -0300 Subject: [PATCH] Save status_msg to accounts.json Restore it if there is not any status_msg set on the server --- src/backend/backend.py | 4 +++- src/backend/matrix_client.py | 42 +++++++++++++++++++++--------------- src/backend/models/items.py | 10 +++++---- src/backend/nio_callbacks.py | 31 ++++++++++++++++++++++---- src/backend/user_files.py | 13 +++++++---- 5 files changed, 70 insertions(+), 30 deletions(-) diff --git a/src/backend/backend.py b/src/backend/backend.py index dcc43452..c8f187d2 100644 --- a/src/backend/backend.py +++ b/src/backend/backend.py @@ -157,6 +157,7 @@ class Backend: device_id: str, homeserver: str = "https://matrix.org", state: str = "online", + status_msg: str = "", ) -> None: """Create and register a `MatrixClient` with known account details.""" @@ -167,7 +168,7 @@ class Backend: self.clients[user_id] = client - await client.resume(user_id, token, device_id, state) + await client.resume(user_id, token, device_id, state, status_msg) async def load_saved_accounts(self) -> List[str]: @@ -185,6 +186,7 @@ class Backend: device_id = info["device_id"], homeserver = info["homeserver"], state = info.get("presence", "online"), + status_msg = info.get("status_msg", ""), ) return user_id diff --git a/src/backend/matrix_client.py b/src/backend/matrix_client.py index eccb7a42..0dea3845 100644 --- a/src/backend/matrix_client.py +++ b/src/backend/matrix_client.py @@ -273,10 +273,11 @@ class MatrixClient(nio.AsyncClient): async def resume( self, - user_id: str, - token: str, - device_id: str, - state: str = "online", + user_id: str, + token: str, + device_id: str, + state: str = "online", + status_msg: str = "", ) -> None: """Login to the server using an existing access token.""" @@ -284,8 +285,9 @@ class MatrixClient(nio.AsyncClient): account = self.models["accounts"][user_id] await self.receive_response(response) - self._presence = "offline" if state == "invisible" else state - account.presence = Presence.State(state) + self._presence = "offline" if state == "invisible" else state + account.presence = Presence.State(state) + account.status_msg = status_msg if state != "offline": account.connecting = True @@ -389,6 +391,12 @@ class MatrixClient(nio.AsyncClient): async def _stop(self) -> None: """Stop client tasks. Will prevent client to receive further events.""" + # Remove account model from presence update + presence = self.backend.presences.get(self.user_id, None) + + if presence: + presence.account = None + tasks = ( self.profile_task, self.sync_task, @@ -404,12 +412,6 @@ class MatrixClient(nio.AsyncClient): self.first_sync_done.clear() - # Remove account model from presence update - presence = self.backend.presences.get(self.user_id, None) - - if presence: - presence.account = None - async def update_own_profile(self) -> None: """Fetch our profile from server and Update our model `Account`.""" @@ -1332,6 +1334,7 @@ class MatrixClient(nio.AsyncClient): status_msg = status_msg if status_msg is not None else ( self.models["accounts"][self.user_id].status_msg ) + set_status_msg = True if presence == "offline": # Do not do anything if account is offline and setting to offline @@ -1348,9 +1351,13 @@ class MatrixClient(nio.AsyncClient): account.presence == Presence.State.offline and presence != "offline" ): + # In this case we will not run super().set_presence() + set_status_msg = False account.connecting = True self.start_task = asyncio.ensure_future(self._start()) + self._presence = "offline" if presence == "invisible" else presence + if ( Presence.State(presence) != account.presence and presence != "offline" @@ -1363,15 +1370,16 @@ class MatrixClient(nio.AsyncClient): if save: account.save_presence = True await self.backend.saved_accounts.update( - self.user_id, presence=presence, + self.user_id, presence=presence, status_msg=status_msg, ) else: account.save_presence = False - await super().set_presence( - "offline" if presence == "invisible" else presence, - status_msg, - ) + if set_status_msg: + await super().set_presence( + "offline" if presence == "invisible" else presence, + status_msg, + ) async def import_keys(self, infile: str, passphrase: str) -> None: diff --git a/src/backend/models/items.py b/src/backend/models/items.py index 1b80b13a..cd5d2fb3 100644 --- a/src/backend/models/items.py +++ b/src/backend/models/items.py @@ -116,10 +116,12 @@ class Presence: ): return - self.account.presence = self.presence if ( - self.account.presence != self.State.echo_invisible - ) else self.State.invisible - self.account.status_msg = self.status_msg + if self.account.presence == self.State.echo_invisible: + self.account.presence = self.State.invisible + else: + self.account.presence = self.presence + self.account.status_msg = self.status_msg + self.account.last_active_at = self.last_active_at self.account.currently_active = self.currently_active diff --git a/src/backend/nio_callbacks.py b/src/backend/nio_callbacks.py index 5c491d60..6d255d46 100644 --- a/src/backend/nio_callbacks.py +++ b/src/backend/nio_callbacks.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: LGPL-3.0-or-later +import asyncio import json import logging as log from dataclasses import dataclass, field @@ -742,6 +743,8 @@ class NioCallbacks: # Check if presence event is ours if ( ev.user_id in self.models["accounts"] and + self.models["accounts"][ev.user_id].presence != + Presence.State.offline and not ( presence.presence == Presence.State.offline and self.models["accounts"][ev.user_id].presence != @@ -750,6 +753,20 @@ class NioCallbacks: ): account = self.models["accounts"][ev.user_id] + # Set status_msg if none is set on the server and we have one + if ( + not presence.status_msg and + account.status_msg and + ev.user_id in self.client.backend.clients and + account.presence != Presence.State.echo_invisible + ): + asyncio.ensure_future( + self.client.backend.clients[ev.user_id].set_presence( + presence.presence.value, + account.status_msg, + ), + ) + # Do not fight back presence from other clients self.client.backend.clients[ev.user_id]._presence = ev.presence @@ -758,11 +775,17 @@ class NioCallbacks: # Save the presence for the next resume if account.save_presence: + status_msg = presence.status_msg + state = presence.presence + + if account.presence == Presence.State.echo_invisible: + status_msg = account.status_msg + state = Presence.State.invisible + await self.client.backend.saved_accounts.update( - user_id = ev.user_id, - presence = presence.presence.value if ( - account.presence != Presence.State.echo_invisible - ) else "invisible", + user_id = ev.user_id, + status_msg = status_msg, + presence = state.value, ) presence.update_account() diff --git a/src/backend/user_files.py b/src/backend/user_files.py index 8145ec30..55fd127e 100644 --- a/src/backend/user_files.py +++ b/src/backend/user_files.py @@ -194,6 +194,7 @@ class Accounts(JSONDataFile): "device_id": client.device_id, "enabled": True, "presence": account.presence.value, + "status_msg": account.status_msg, "order": account.order, }, }) @@ -201,10 +202,11 @@ class Accounts(JSONDataFile): async def update( self, - user_id: str, - enabled: Optional[str] = None, - presence: Optional[str] = None, - order: Optional[int] = None, + user_id: str, + enabled: Optional[str] = None, + presence: Optional[str] = None, + order: Optional[int] = None, + status_msg: Optional[str] = None, ) -> None: """Update an account if found in the config file and write to disk.""" @@ -222,6 +224,9 @@ class Accounts(JSONDataFile): if order is not None: saved[user_id]["order"] = order + if status_msg is not None: + saved[user_id]["status_msg"] = status_msg + await self.write({**saved})