From 1f3022b8cf42005fd6dd8d6731ada2dfa8b6c399 Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:00:52 -0600 Subject: [PATCH 01/15] Respond to pings on the mesh --- plugins/ping_plugin.py | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/plugins/ping_plugin.py b/plugins/ping_plugin.py index e0c422e..ff68e62 100644 --- a/plugins/ping_plugin.py +++ b/plugins/ping_plugin.py @@ -1,32 +1,31 @@ from plugins.base_plugin import BasePlugin - +import re class Plugin(BasePlugin): plugin_name = "ping" @property def description(self): - return "Check connectivity with the relay" + return "Check connectivity with the relay or respond to pings over the mesh" async def handle_meshtastic_message( self, packet, formatted_message, longname, meshnet_name ): - if ( - "decoded" in packet - and "portnum" in packet["decoded"] - and packet["decoded"]["portnum"] == "TEXT_MESSAGE_APP" - and "text" in packet["decoded"] - ): - message = packet["decoded"]["text"] - message = message.strip() - if f"!{self.plugin_name}" not in message: - return - - from meshtastic_utils import connect_meshtastic - - meshtastic_client = connect_meshtastic() - meshtastic_client.sendText(text="pong!", destinationId=packet["fromId"]) - return True + if "decoded" in packet and "text" in packet["decoded"]: + message = packet["decoded"]["text"].strip() + if re.search(r"\bping\b", message, re.IGNORECASE) or "!ping" in message: + from meshtastic_utils import connect_meshtastic + + meshtastic_client = connect_meshtastic() + channel = packet.get("channel", 0) # Default to channel 0 if not provided + reply_message = "pong!" + if longname: + reply_message = f"{longname}: pong!" + + meshtastic_client.sendText( + text=reply_message, channelIndex=channel + ) + return True def get_matrix_commands(self): return [self.plugin_name] From fadd78a25b9985968c06df6084ebfe769375b385 Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:18:06 -0600 Subject: [PATCH 02/15] Adjust mesh ping behavior --- plugins/ping_plugin.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/plugins/ping_plugin.py b/plugins/ping_plugin.py index ff68e62..6c90ebf 100644 --- a/plugins/ping_plugin.py +++ b/plugins/ping_plugin.py @@ -13,14 +13,23 @@ async def handle_meshtastic_message( ): if "decoded" in packet and "text" in packet["decoded"]: message = packet["decoded"]["text"].strip() - if re.search(r"\bping\b", message, re.IGNORECASE) or "!ping" in message: + + # Match "ping" anywhere in the message with optional punctuation + match = re.search(r"\b(ping[\?!]{0,5})\b", message, re.IGNORECASE) + if match: from meshtastic_utils import connect_meshtastic meshtastic_client = connect_meshtastic() channel = packet.get("channel", 0) # Default to channel 0 if not provided - reply_message = "pong!" - if longname: - reply_message = f"{longname}: pong!" + + # Get the matched case and punctuation + matched_text = match.group(1) + base_response = "pong" + if len(re.findall(r"[!?]", matched_text)) > 5: + reply_message = "Pong..." + else: + # Preserve case and punctuation + reply_message = re.sub(r"ping", base_response, matched_text, flags=re.IGNORECASE) meshtastic_client.sendText( text=reply_message, channelIndex=channel From da522d17e11ae3cd24455c39ab8d9ac826e263f7 Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:23:51 -0600 Subject: [PATCH 03/15] Pong matches case and punctuation --- plugins/ping_plugin.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/ping_plugin.py b/plugins/ping_plugin.py index 6c90ebf..bf94ca2 100644 --- a/plugins/ping_plugin.py +++ b/plugins/ping_plugin.py @@ -15,7 +15,7 @@ async def handle_meshtastic_message( message = packet["decoded"]["text"].strip() # Match "ping" anywhere in the message with optional punctuation - match = re.search(r"\b(ping[\?!]{0,5})\b", message, re.IGNORECASE) + match = re.search(r"\b(ping[\?!]*)\b", message, re.IGNORECASE) if match: from meshtastic_utils import connect_meshtastic @@ -24,12 +24,13 @@ async def handle_meshtastic_message( # Get the matched case and punctuation matched_text = match.group(1) - base_response = "pong" - if len(re.findall(r"[!?]", matched_text)) > 5: + punctuation_count = len(re.findall(r"[!?]", matched_text)) + + if punctuation_count > 5: reply_message = "Pong..." else: - # Preserve case and punctuation - reply_message = re.sub(r"ping", base_response, matched_text, flags=re.IGNORECASE) + # Replace "ping" with "pong" and preserve case and punctuation + reply_message = re.sub(r"ping", "pong", matched_text, flags=re.IGNORECASE) meshtastic_client.sendText( text=reply_message, channelIndex=channel From 4c4123dc9c91f9576c9490c97651df16cab75d35 Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:25:45 -0600 Subject: [PATCH 04/15] Handle both case and punctuation properly --- plugins/ping_plugin.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/ping_plugin.py b/plugins/ping_plugin.py index bf94ca2..500899e 100644 --- a/plugins/ping_plugin.py +++ b/plugins/ping_plugin.py @@ -29,8 +29,15 @@ async def handle_meshtastic_message( if punctuation_count > 5: reply_message = "Pong..." else: - # Replace "ping" with "pong" and preserve case and punctuation - reply_message = re.sub(r"ping", "pong", matched_text, flags=re.IGNORECASE) + # Replace "ping" with "pong" while preserving case and punctuation + base_response = "pong" + if matched_text.isupper(): + base_response = base_response.upper() + elif matched_text[0].isupper(): + base_response = base_response.capitalize() + + # Add the same punctuation from the input + reply_message = base_response + re.sub(r"[a-zA-Z]", "", matched_text) meshtastic_client.sendText( text=reply_message, channelIndex=channel From 65d08596e6c06a4d3d7eae4d7bb7f41bf129d462 Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:27:56 -0600 Subject: [PATCH 05/15] Another attempt at preserving punctuation --- plugins/ping_plugin.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/ping_plugin.py b/plugins/ping_plugin.py index 500899e..1c13e69 100644 --- a/plugins/ping_plugin.py +++ b/plugins/ping_plugin.py @@ -24,20 +24,20 @@ async def handle_meshtastic_message( # Get the matched case and punctuation matched_text = match.group(1) - punctuation_count = len(re.findall(r"[!?]", matched_text)) + base_response = "pong" - if punctuation_count > 5: + # Preserve case + if matched_text.isupper(): + base_response = base_response.upper() + elif matched_text[0].isupper(): + base_response = base_response.capitalize() + + # Add the exact punctuation from the input + reply_message = base_response + matched_text[len("ping"):] + + # Handle excessive punctuation (more than 5 ! or ?) + if len(re.findall(r"[!?]", matched_text)) > 5: reply_message = "Pong..." - else: - # Replace "ping" with "pong" while preserving case and punctuation - base_response = "pong" - if matched_text.isupper(): - base_response = base_response.upper() - elif matched_text[0].isupper(): - base_response = base_response.capitalize() - - # Add the same punctuation from the input - reply_message = base_response + re.sub(r"[a-zA-Z]", "", matched_text) meshtastic_client.sendText( text=reply_message, channelIndex=channel From cebd1dd7c78a0430e1be4376bc03bb3583c122b6 Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:29:09 -0600 Subject: [PATCH 06/15] Match and preserve case --- plugins/ping_plugin.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/ping_plugin.py b/plugins/ping_plugin.py index 1c13e69..33f1382 100644 --- a/plugins/ping_plugin.py +++ b/plugins/ping_plugin.py @@ -26,18 +26,18 @@ async def handle_meshtastic_message( matched_text = match.group(1) base_response = "pong" - # Preserve case + # Match and preserve case if matched_text.isupper(): base_response = base_response.upper() elif matched_text[0].isupper(): base_response = base_response.capitalize() - # Add the exact punctuation from the input - reply_message = base_response + matched_text[len("ping"):] - - # Handle excessive punctuation (more than 5 ! or ?) - if len(re.findall(r"[!?]", matched_text)) > 5: + # Preserve punctuation from the original match + punctuation = re.sub(r"[a-zA-Z]", "", matched_text) + if len(punctuation) > 5: # Handle excessive punctuation reply_message = "Pong..." + else: + reply_message = base_response + punctuation meshtastic_client.sendText( text=reply_message, channelIndex=channel From ea18bed3f93f179e32892a100447b205ae892722 Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:31:54 -0600 Subject: [PATCH 07/15] New attempt --- plugins/ping_plugin.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/plugins/ping_plugin.py b/plugins/ping_plugin.py index 33f1382..9ad58bd 100644 --- a/plugins/ping_plugin.py +++ b/plugins/ping_plugin.py @@ -14,31 +14,36 @@ async def handle_meshtastic_message( if "decoded" in packet and "text" in packet["decoded"]: message = packet["decoded"]["text"].strip() - # Match "ping" anywhere in the message with optional punctuation - match = re.search(r"\b(ping[\?!]*)\b", message, re.IGNORECASE) + # Match "ping" followed by optional punctuation + match = re.search(r"\b(ping[!?]*)\b", message, re.IGNORECASE) if match: from meshtastic_utils import connect_meshtastic meshtastic_client = connect_meshtastic() channel = packet.get("channel", 0) # Default to channel 0 if not provided - # Get the matched case and punctuation + # Extract matched text matched_text = match.group(1) + + # Define the base response base_response = "pong" - # Match and preserve case + # Preserve case of the matched word if matched_text.isupper(): base_response = base_response.upper() elif matched_text[0].isupper(): base_response = base_response.capitalize() - # Preserve punctuation from the original match - punctuation = re.sub(r"[a-zA-Z]", "", matched_text) - if len(punctuation) > 5: # Handle excessive punctuation + # Extract and preserve punctuation from the matched text + punctuation = matched_text[len("ping"):] # Punctuation after "ping" + + # If there are more than 5 punctuation marks, default to "Pong..." + if len(punctuation) > 5: reply_message = "Pong..." else: reply_message = base_response + punctuation + # Send the reply back to the same channel meshtastic_client.sendText( text=reply_message, channelIndex=channel ) From d69ba890323f0bd8ec24ea161ef71e8fa468ae64 Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:41:24 -0600 Subject: [PATCH 08/15] Deep thinking --- plugins/ping_plugin.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/plugins/ping_plugin.py b/plugins/ping_plugin.py index 9ad58bd..0071c45 100644 --- a/plugins/ping_plugin.py +++ b/plugins/ping_plugin.py @@ -1,8 +1,11 @@ -from plugins.base_plugin import BasePlugin import re +import string +import logging +from plugins.base_plugin import BasePlugin class Plugin(BasePlugin): plugin_name = "ping" + punctuation = string.punctuation @property def description(self): @@ -14,18 +17,17 @@ async def handle_meshtastic_message( if "decoded" in packet and "text" in packet["decoded"]: message = packet["decoded"]["text"].strip() - # Match "ping" followed by optional punctuation - match = re.search(r"\b(ping[!?]*)\b", message, re.IGNORECASE) + # Create a regex pattern that matches "ping" followed by 0-5 punctuation marks + pattern = rf"\b(ping[{re.escape(string.punctuation)}]{{0,5}})\b" + match = re.search(pattern, message, re.IGNORECASE) if match: from meshtastic_utils import connect_meshtastic meshtastic_client = connect_meshtastic() channel = packet.get("channel", 0) # Default to channel 0 if not provided - # Extract matched text matched_text = match.group(1) - # Define the base response base_response = "pong" # Preserve case of the matched word @@ -34,19 +36,18 @@ async def handle_meshtastic_message( elif matched_text[0].isupper(): base_response = base_response.capitalize() - # Extract and preserve punctuation from the matched text - punctuation = matched_text[len("ping"):] # Punctuation after "ping" - - # If there are more than 5 punctuation marks, default to "Pong..." - if len(punctuation) > 5: + # Extract punctuation from the matched text + punctuation_part = re.sub(r'^ping', '', matched_text, flags=re.IGNORECASE) + if len(punctuation_part) > 5: reply_message = "Pong..." else: - reply_message = base_response + punctuation + reply_message = base_response + punctuation_part # Send the reply back to the same channel - meshtastic_client.sendText( - text=reply_message, channelIndex=channel - ) + try: + meshtastic_client.sendText( + text=reply_message, channelIndex=channel + ) return True def get_matrix_commands(self): @@ -61,4 +62,4 @@ async def handle_room_message(self, room, event, full_message): return False await self.send_matrix_message(room.room_id, "pong!") - return True + return True \ No newline at end of file From ab8190d23a44719ab1c453db0ac29ad6c812e953 Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:44:47 -0600 Subject: [PATCH 09/15] upgrade trunk --- .trunk/trunk.yaml | 15 ++++++++------- log_utils.py | 14 +++++++++++--- meshtastic_utils.py | 14 ++++---------- plugins/map_plugin.py | 3 ++- plugins/ping_plugin.py | 2 ++ sample_config.yaml | 1 - 6 files changed, 27 insertions(+), 22 deletions(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 9d9c4d7..f0d528e 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -7,7 +7,7 @@ cli: plugins: sources: - id: trunk - ref: v1.6.4 + ref: v1.6.5 uri: https://github.com/trunk-io/plugins # Many linters and tools depend on runtimes - configure them here. (https://docs.trunk.io/runtimes) runtimes: @@ -17,17 +17,18 @@ runtimes: # This is the section where you manage your linters. (https://docs.trunk.io/check/configuration) lint: enabled: + - taplo@0.9.3 - actionlint@1.7.4 - - bandit@1.7.10 + - bandit@1.8.0 - black@24.10.0 - - checkov@3.2.287 + - checkov@3.2.317 - git-diff-check - isort@5.13.2 - - markdownlint@0.42.0 + - markdownlint@0.43.0 - osv-scanner@1.9.1 - - prettier@3.3.3 - - ruff@0.7.3 - - trufflehog@3.83.6 + - prettier@3.4.1 + - ruff@0.8.0 + - trufflehog@3.84.1 - yamllint@1.35.1 actions: disabled: diff --git a/log_utils.py b/log_utils.py index 4f50746..a66ba46 100644 --- a/log_utils.py +++ b/log_utils.py @@ -1,8 +1,10 @@ import logging import os from logging.handlers import RotatingFileHandler + from config import relay_config + def get_logger(name): logger = logging.getLogger(name=name) log_level = getattr(logging, relay_config["logging"]["level"].upper()) @@ -31,9 +33,15 @@ def get_logger(name): os.makedirs(log_dir, exist_ok=True) # Set up size-based log rotation - max_bytes = relay_config["logging"].get("max_log_size", 10 * 1024 * 1024) # Default 10 MB - backup_count = relay_config["logging"].get("backup_count", 1) # Default to 1 backup - file_handler = RotatingFileHandler(log_file, maxBytes=max_bytes, backupCount=backup_count) + max_bytes = relay_config["logging"].get( + "max_log_size", 10 * 1024 * 1024 + ) # Default 10 MB + backup_count = relay_config["logging"].get( + "backup_count", 1 + ) # Default to 1 backup + file_handler = RotatingFileHandler( + log_file, maxBytes=max_bytes, backupCount=backup_count + ) file_handler.setFormatter( logging.Formatter( diff --git a/meshtastic_utils.py b/meshtastic_utils.py index b742fa6..020857a 100644 --- a/meshtastic_utils.py +++ b/meshtastic_utils.py @@ -152,9 +152,7 @@ def connect_meshtastic(force_connect=False): ) time.sleep(wait_time) else: - logger.error( - f"Could not connect after {retry_limit} attempts: {e}" - ) + logger.error(f"Could not connect after {retry_limit} attempts: {e}") return None return meshtastic_client @@ -191,9 +189,7 @@ def on_lost_meshtastic_connection(interface=None): meshtastic_client = None if event_loop: - reconnect_task = asyncio.run_coroutine_threadsafe( - reconnect(), event_loop - ) + reconnect_task = asyncio.run_coroutine_threadsafe(reconnect(), event_loop) async def reconnect(): @@ -210,9 +206,7 @@ async def reconnect(): ) await asyncio.sleep(backoff_time) if shutting_down: - logger.info( - "Shutdown in progress. Aborting reconnection attempts." - ) + logger.info("Shutdown in progress. Aborting reconnection attempts.") break meshtastic_client = connect_meshtastic(force_connect=True) if meshtastic_client: @@ -247,7 +241,7 @@ def on_meshtastic_message(packet, interface): loop = event_loop - sender = packet.get('fromId') or packet.get('from') + sender = packet.get("fromId") or packet.get("from") decoded = packet.get("decoded", {}) text = decoded.get("text") diff --git a/plugins/map_plugin.py b/plugins/map_plugin.py index 4c2756c..c2950fd 100644 --- a/plugins/map_plugin.py +++ b/plugins/map_plugin.py @@ -6,14 +6,15 @@ import s2sphere import staticmaps -from log_utils import get_logger from nio import AsyncClient, UploadResponse from PIL import Image, ImageFont +from log_utils import get_logger from plugins.base_plugin import BasePlugin logger = get_logger(__name__) + class TextLabel(staticmaps.Object): def __init__(self, latlng: s2sphere.LatLng, text: str, fontSize: int = 12) -> None: staticmaps.Object.__init__(self) diff --git a/plugins/ping_plugin.py b/plugins/ping_plugin.py index 0071c45..fafe31b 100644 --- a/plugins/ping_plugin.py +++ b/plugins/ping_plugin.py @@ -48,6 +48,8 @@ async def handle_meshtastic_message( meshtastic_client.sendText( text=reply_message, channelIndex=channel ) + except Exception as e: + self.logger.error(f"Error sending text: {e}") return True def get_matrix_commands(self): diff --git a/sample_config.yaml b/sample_config.yaml index f3294eb..865ddba 100644 --- a/sample_config.yaml +++ b/sample_config.yaml @@ -32,7 +32,6 @@ plugins: nodes: active: true # Other core plugins.. - #community-plugins: # Note: Community plugins are a new feature. Please report any issues. # sample_plugin: # active: true From e01ce977a57dcddd8ca598ace64372ebe9077d17 Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:54:52 -0600 Subject: [PATCH 10/15] Bringing out the big guns --- plugins/ping_plugin.py | 87 ++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/plugins/ping_plugin.py b/plugins/ping_plugin.py index fafe31b..bb7dda4 100644 --- a/plugins/ping_plugin.py +++ b/plugins/ping_plugin.py @@ -1,8 +1,9 @@ import re import string -import logging + from plugins.base_plugin import BasePlugin + class Plugin(BasePlugin): plugin_name = "ping" punctuation = string.punctuation @@ -11,46 +12,48 @@ class Plugin(BasePlugin): def description(self): return "Check connectivity with the relay or respond to pings over the mesh" - async def handle_meshtastic_message( - self, packet, formatted_message, longname, meshnet_name - ): - if "decoded" in packet and "text" in packet["decoded"]: - message = packet["decoded"]["text"].strip() - - # Create a regex pattern that matches "ping" followed by 0-5 punctuation marks - pattern = rf"\b(ping[{re.escape(string.punctuation)}]{{0,5}})\b" - match = re.search(pattern, message, re.IGNORECASE) - if match: - from meshtastic_utils import connect_meshtastic - - meshtastic_client = connect_meshtastic() - channel = packet.get("channel", 0) # Default to channel 0 if not provided - - matched_text = match.group(1) - - base_response = "pong" - - # Preserve case of the matched word - if matched_text.isupper(): - base_response = base_response.upper() - elif matched_text[0].isupper(): - base_response = base_response.capitalize() - - # Extract punctuation from the matched text - punctuation_part = re.sub(r'^ping', '', matched_text, flags=re.IGNORECASE) - if len(punctuation_part) > 5: - reply_message = "Pong..." - else: - reply_message = base_response + punctuation_part - - # Send the reply back to the same channel - try: - meshtastic_client.sendText( - text=reply_message, channelIndex=channel - ) - except Exception as e: - self.logger.error(f"Error sending text: {e}") - return True + +async def handle_meshtastic_message( + self, packet, formatted_message, longname, meshnet_name +): + if "decoded" in packet and "text" in packet["decoded"]: + message = packet["decoded"]["text"].strip() + + # Updated regex to match optional punctuation before and after "ping" + match = re.search(r"(? 5: + reply_message = "Pong..." + else: + reply_message = pre_punc + base_response + post_punc + + # Send the reply back to the same channel + meshtastic_client.sendText(text=reply_message, channelIndex=channel) + return True def get_matrix_commands(self): return [self.plugin_name] @@ -64,4 +67,4 @@ async def handle_room_message(self, room, event, full_message): return False await self.send_matrix_message(room.room_id, "pong!") - return True \ No newline at end of file + return True From eafc6331ab14f2644d4e7e7bf26e36a42109e701 Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:56:55 -0600 Subject: [PATCH 11/15] fix indentation --- plugins/ping_plugin.py | 87 ++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/plugins/ping_plugin.py b/plugins/ping_plugin.py index bb7dda4..2d0c72c 100644 --- a/plugins/ping_plugin.py +++ b/plugins/ping_plugin.py @@ -12,48 +12,51 @@ class Plugin(BasePlugin): def description(self): return "Check connectivity with the relay or respond to pings over the mesh" - -async def handle_meshtastic_message( - self, packet, formatted_message, longname, meshnet_name -): - if "decoded" in packet and "text" in packet["decoded"]: - message = packet["decoded"]["text"].strip() - - # Updated regex to match optional punctuation before and after "ping" - match = re.search(r"(? 5: - reply_message = "Pong..." - else: - reply_message = pre_punc + base_response + post_punc - - # Send the reply back to the same channel - meshtastic_client.sendText(text=reply_message, channelIndex=channel) - return True + async def handle_meshtastic_message( + self, packet, formatted_message, longname, meshnet_name + ): + if "decoded" in packet and "text" in packet["decoded"]: + message = packet["decoded"]["text"].strip() + + # Updated regex to match optional punctuation before and after "ping" + match = re.search( + r"(? 5: + reply_message = "Pong..." + else: + reply_message = pre_punc + base_response + post_punc + + # Send the reply back to the same channel + meshtastic_client.sendText(text=reply_message, channelIndex=channel) + return True def get_matrix_commands(self): return [self.plugin_name] From 1a0ef7c870e8d26014b8cb8acff337bd8e750f2a Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Wed, 27 Nov 2024 17:02:35 -0600 Subject: [PATCH 12/15] Adjust spacing --- sample_config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sample_config.yaml b/sample_config.yaml index 865ddba..19fa7c1 100644 --- a/sample_config.yaml +++ b/sample_config.yaml @@ -25,13 +25,13 @@ logging: #max_log_size: 10485760 # 10 MB default if omitted #backup_count: 3 # Keeps 1 backup as the default if omitted -#Note: Some plugins are experimental and some need maintenance. +#These are core Plugins - Note: Some plugins are experimental and some need maintenance. plugins: health: active: true nodes: active: true - # Other core plugins.. + #community-plugins: # Note: Community plugins are a new feature. Please report any issues. # sample_plugin: # active: true From b7ccf85dc6fd32a4a750e1d157fc2bbe641a96ae Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Thu, 28 Nov 2024 08:40:24 -0600 Subject: [PATCH 13/15] Match default in backup count default in sample config --- sample_config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample_config.yaml b/sample_config.yaml index 19fa7c1..d2bda75 100644 --- a/sample_config.yaml +++ b/sample_config.yaml @@ -23,7 +23,7 @@ logging: #log_to_file: true # Default is false #filename: logs/mmrelay.log # Default location #max_log_size: 10485760 # 10 MB default if omitted - #backup_count: 3 # Keeps 1 backup as the default if omitted + #backup_count: 1 # Keeps 1 backup as the default if omitted #These are core Plugins - Note: Some plugins are experimental and some need maintenance. plugins: From 8c78ef916aaf9a70901ced6da8a8950d916adea7 Mon Sep 17 00:00:00 2001 From: fernandodpr Date: Wed, 27 Nov 2024 23:57:44 +0100 Subject: [PATCH 14/15] feat: Extend plugin configuration loader to support dynamic levels Previously, the configuration loader in `BasePlugin` only supported loading plugin configurations from the `plugins` section of the `config.yaml` file. This approach limited flexibility and made it incompatible with new configuration structures. With this update, the configuration loader now supports additional sections, such as `community-plugins` and `custom-plugins`, while maintaining backward compatibility. Plugins can access their configurations regardless of where they are defined in the file. - Added dynamic search across multiple levels: `plugins`, `community-plugins`, and `custom-plugins`. - Ensured `plugins` is prioritized to avoid breaking existing setups. - Plugins retain access to their full configuration through `self.config`. How to access configuration in plugins: - Use `self.config` to retrieve plugin-specific options. - Example: `self.config.get('active', False)` checks if the plugin is active. - All configuration options from the corresponding section (e.g., `plugins`, `community-plugins`) are available dynamically. --- plugins/base_plugin.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/base_plugin.py b/plugins/base_plugin.py index 1952ddb..b9c13fd 100644 --- a/plugins/base_plugin.py +++ b/plugins/base_plugin.py @@ -28,8 +28,12 @@ def __init__(self) -> None: super().__init__() self.logger = get_logger(f"Plugin:{self.plugin_name}") self.config = {"active": False} - if "plugins" in relay_config and self.plugin_name in relay_config["plugins"]: - self.config = relay_config["plugins"][self.plugin_name] + plugin_levels = ["plugins", "community-plugins", "custom-plugins"] + + for level in plugin_levels: + if level in relay_config and self.plugin_name in relay_config[level]: + self.config = relay_config[level][self.plugin_name] + break def start(self): if "schedule" not in self.config or ( From 7a9299252b0ec06cab23616c30ac03167d2efb7e Mon Sep 17 00:00:00 2001 From: Jeremiah K <17190268+jeremiah-k@users.noreply.github.com> Date: Thu, 28 Nov 2024 09:59:12 -0600 Subject: [PATCH 15/15] Add match_case function --- plugins/ping_plugin.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/ping_plugin.py b/plugins/ping_plugin.py index 2d0c72c..cdf51ce 100644 --- a/plugins/ping_plugin.py +++ b/plugins/ping_plugin.py @@ -3,6 +3,11 @@ from plugins.base_plugin import BasePlugin +def match_case(source, target): + return ''.join( + c.upper() if s.isupper() else c.lower() + for s, c in zip(source, target) + ) class Plugin(BasePlugin): plugin_name = "ping" @@ -40,13 +45,8 @@ async def handle_meshtastic_message( # Define the base response base_response = "pong" - # Preserve case of the matched word - if matched_text.isupper(): - base_response = base_response.upper() - elif matched_text[0].isupper(): - base_response = base_response.capitalize() - else: - base_response = base_response.lower() + # Adjust base_response to match the case pattern of matched_text + base_response = match_case(matched_text, base_response) # Construct the reply message if total_punc_length > 5: