From 0fccf6ea9e2aca5239c52389f5895e7f36bcd77b Mon Sep 17 00:00:00 2001 From: Geoff Whittington Date: Sat, 11 Feb 2023 22:43:51 -0500 Subject: [PATCH] Add support for NoStr --- README.md | 23 +++++++++++++++ main.py | 2 -- plugins.py | 75 ++++++++++++++++++++++++++++++++++++++++++++++-- requirements.txt | 1 + 4 files changed, 97 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 514f59e..1e61e1b 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ The following plugins can be used in the `pipelines` section of `config.yaml`: | `encrypt_filter` | Encrypt a packet for a desired MQTT recipient | | `decrypt_filter` | Decrypt a packet originating from MQTT | | `radio_message_plugin` | Send a packet to a specified `device` | +| `nostr_plugin` | Send a NoStr event to a relay | ### debugger - Output the contents of a packet @@ -238,6 +239,28 @@ decrypt_filter: key: '/home/user/keys/key.pem' ``` +### nostr_plugin - Send a NoStr event + +- **log_level** `debug` or `info`. Default `info` +- **private_key** The private key for a NoStr user. Secrets can be passed using ENV variables +- **public_key** The public key for the NoStr user associated with the private key. +- **message** A specific message +- **relays** List of NoStr relays + +For example: + +``` +nostr_plugin: + private_key: "{NOSTR_PRIVATE_KEY}" + public_key: "npub1d0ja5d.......xw7jys4eqnk0" + relays: + - "wss://nostr-pub.wellorder.net" +``` + +Placeholders can be used with the **message** value: + +- `{MSG}` - Packet text + ### radio_message_plugin - Send a packet to a radio - **log_level** `debug` or `info`. Default `info` diff --git a/main.py b/main.py index 5ad6b92..ec35b95 100644 --- a/main.py +++ b/main.py @@ -42,7 +42,6 @@ def onReceive(packet, interface): # called when a packet arrives continue for plugin_key, plugin_config in plugin.items(): - logger.debug(f"Processing plugin: {pipeline}/{plugin_key}") if not pipeline_packet: logger.debug("Skipping since the packet is null") @@ -146,7 +145,6 @@ if "mqtt_servers" in bridge_config: pipeline_packet = p.do_action(orig_packet) for pipeline, pipeline_plugins in config["pipelines"].items(): - packet = pipeline_packet logger.debug(f"MQTT {config['name']} pipeline {pipeline} initiated") diff --git a/plugins.py b/plugins.py index cab2444..290d2e9 100644 --- a/plugins.py +++ b/plugins.py @@ -6,7 +6,7 @@ import json import logging import os import re - +import ssl plugins = {} @@ -322,7 +322,6 @@ class EncryptFilter(Plugin): logger = logging.getLogger(name="meshtastic.bridge.filter.encrypt") def do_action(self, packet): - if "key" not in self.config: return None @@ -453,3 +452,75 @@ class RadioMessagePlugin(Plugin): plugins["radio_message_plugin"] = RadioMessagePlugin() + + +import time +from nostr.event import Event +from nostr.relay_manager import RelayManager +from nostr.message_type import ClientMessageType +from nostr.key import PrivateKey, PublicKey + + +class NoStrPlugin(Plugin): + logger = logging.getLogger(name="meshtastic.bridge.plugin.nostr_send") + + def do_action(self, packet): + relays = ["wss://nostr-pub.wellorder.net", "wss://relay.damus.io"] + + for config_value in ["private_key", "public_key"]: + if config_value not in self.config: + self.logger.debug(f"Missing {config_value}") + return packet + + # configure relays + if "relays" in self.config: + for relay in self.config["relays"]: + relays.append(relay) + + relay_manager = RelayManager() + + for relay in relays: + relay_manager.add_relay(relay) + + self.logger.debug(f"Opening connection to NoStr relays...") + + relay_manager.open_connections( + {"cert_reqs": ssl.CERT_NONE} + ) # NOTE: This disables ssl certificate verification + time.sleep( + self.config["startup_wait"] if "startup_wait" in self.config else 1.25 + ) # allow the connections to open + + # Opportunistically use environment variable + for ek, ev in os.environ.items(): + needle = "{" + ek + "}" + if needle in self.config["private_key"]: + self.config["private_key"] = self.config["private_key"].replace( + needle, ev + ) + + private_key = PrivateKey.from_nsec(self.config["private_key"]) + public_key = PublicKey.from_npub(self.config["public_key"]) + + if "message" in self.config: + message = self.config["message"].replace("{MSG}", packet["decoded"]["text"]) + else: + message = packet["decoded"]["text"] + + event = Event(content=message, public_key=public_key.hex()) + private_key.sign_event(event) + + self.logger.debug(f"Sending message to NoStr ...") + relay_manager.publish_event(event) + self.logger.info(f"Sent message to NoStr") + + time.sleep( + self.config["publish_wait"] if "publish_wait" in self.config else 1 + ) # allow the messages to send + + relay_manager.close_connections() + + return packet + + +plugins["nostr_plugin"] = NoStrPlugin() diff --git a/requirements.txt b/requirements.txt index 6f786ac..b46c72c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ requests pyyaml paho-mqtt jwcrypto +nostr \ No newline at end of file