From 29f38414eba0ed5893578c382eae558a826475de Mon Sep 17 00:00:00 2001 From: sdb9696 Date: Wed, 25 Oct 2023 12:13:22 +0100 Subject: [PATCH] Update handling of no event loop and bump version --- docs/source/conf.py | 5 ++++- firebase_messaging/fcmpushclient.py | 29 ++++++++++++++++++++++------- pyproject.toml | 2 +- tests/test_fcmpushclient.py | 17 +++++++++++++---- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 83132f5..f6ca0a2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -3,13 +3,16 @@ # For the full list of built-in configuration values, see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html +from importlib.metadata import version as _version + # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information project = "firebase-messaging" copyright = "2023, Steven Beth" author = "Steven Beth" -release = "0.1.1" +release = _version("firebase_messaging") +version = _version("firebase_messaging") # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/firebase_messaging/fcmpushclient.py b/firebase_messaging/fcmpushclient.py index 64cc87c..582063a 100644 --- a/firebase_messaging/fcmpushclient.py +++ b/firebase_messaging/fcmpushclient.py @@ -125,9 +125,6 @@ def __init__( self.last_login_time = None self.last_message_time = None - self.reset_lock = asyncio.Lock() - self.stopping_lock = asyncio.Lock() - self.is_resetting = False self.is_stopping = False self.tasks = None @@ -139,6 +136,9 @@ def __init__( self.app_id = None self.sender_id = None + self.reset_lock = asyncio.Lock() + self.stopping_lock = asyncio.Lock() + def _msg_str(self, msg): if self.config.log_debug_verbose: return type(msg).__name__ + "\n" + MessageToJson(msg, indent=4) @@ -375,9 +375,14 @@ def _handle_data_message(self, callback, p, obj): decrypted = self._decrypt_raw_data( self.credentials, crypto_key, salt, p.raw_data ) - decrypted_json = json.loads(decrypted.decode("utf-8")) + try: + decrypted_json = json.loads(decrypted.decode("utf-8")) + except (json.JSONDecodeError, ValueError): + pass + + ret_val = decrypted_json if decrypted_json else decrypted self._log_verbose( - "Decrypted data for message %s is: %s", p.persistent_id, decrypted_json + "Decrypted data for message %s is: %s", p.persistent_id, ret_val ) if self.main_loop and self.main_loop.is_running(): if callback: @@ -388,7 +393,7 @@ def _handle_data_message(self, callback, p, obj): self.loop, on_error, callback, - decrypted_json, + ret_val, p, obj, ) @@ -723,7 +728,17 @@ def connect( obj: returns the arbitrary object if supplied to this function. :param obj: Arbitrary object to be returned in the callback. """ - self.main_loop = asyncio.get_running_loop() + try: + self.main_loop = asyncio.get_running_loop() + except RuntimeError: + _logger.error( + "No running event loop, connect failed. " + + "FcMPushClient needs a running event loop to call back on" + ) + return + + self.reset_lock = asyncio.Lock() + self.stopping_lock = asyncio.Lock() self.fcm_thread = Thread( target=self._start_connection, args=[callback, obj], daemon=True diff --git a/pyproject.toml b/pyproject.toml index 62a4d64..63da656 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "firebase-messaging" -version = "0.1.1" +version = "0.1.2" description = "FCM/GCM push notification client" authors = ["sdb9696 "] license = "MIT" diff --git a/tests/test_fcmpushclient.py b/tests/test_fcmpushclient.py index 9a8946f..32cd25f 100644 --- a/tests/test_fcmpushclient.py +++ b/tests/test_fcmpushclient.py @@ -38,7 +38,7 @@ async def test_login(logged_in_push_client, fake_mcs_endpoint, mocker, caplog): assert len([record for record in caplog.records if record.levelname == "ERROR"]) == 0 assert "Succesfully logged in to MCS endpoint" in [record.message for record in caplog.records if record.levelname == "INFO"] - +#@pytest.mark.parametrize("raw_data", [1,2,3,6]) async def test_data_message_receive(logged_in_push_client, fake_mcs_endpoint, mocker, caplog): notification = None @@ -138,6 +138,17 @@ async def test_heartbeat_send(logged_in_push_client, fake_mcs_endpoint, mocker, assert len([record.message for record in caplog.records if record.levelname == "DEBUG" and "Received heartbeat ack" in record.message] ) == 1 +def test_no_loop(caplog): + + pr = FcmPushClient() + pr.connect(None) + + msg = ( + "No running event loop, connect failed. " + + "FcMPushClient needs a running event loop to call back on" + ) + assert len([record.message for record in caplog.records if record.levelname == "ERROR" and msg == record.message] ) == 1 + async def test_decrypt(): def get_app_data_by_key(msg, key): for x in msg.app_data: @@ -155,17 +166,15 @@ def set_app_data_by_key(msg, key, value): salt_str = get_app_data_by_key(dms, "encryption")[5:] salt = urlsafe_b64decode(salt_str.encode("ascii")) - #crypto_key = get_app_data_by_key(dms, "crypto-key")[3:] # Random key pair sender_pub = 'BAGEFtID7WlmwzQ9pbjdRYAhfPe7Z8lA3ZGIPUh0SE3ikoY2PIrWUP0rmhpE4Kl8ImgMUDjKWrz0WmtLxORIHuw' - #sender_pub_dh = urlsafe_b64decode(sender_pub.encode("ascii") ) sender_pri_der = urlsafe_b64decode('MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgwSUpDfIqdJG3XVkn7t1GExHuW3gsqD4-J525w-rnCIihRANCAAQBhBbSA-1pZsM0PaW43UWAIXz3u2fJQN2RiD1IdEhN4pKGNjyK1lD9K5oaROCpfCJoDFA4ylq89FprS8TkSB7s'.encode("ascii") + b"========") sender_privkey = load_der_private_key( sender_pri_der, password=None, backend=default_backend() ) - # secret = 'NENKX5zJRTFx5bGWBM7C_A' + sender_sec = urlsafe_b64decode(credentials["keys"]["secret"].encode("ascii") + b"========") receiver_pub_key = urlsafe_b64decode(credentials["keys"]["public"].encode("ascii") + b"=") raw_data_encrypted = encrypt(