Added plugin functionality

This commit is contained in:
Mark Qvist 2024-03-25 00:58:58 +01:00
parent 02805290b0
commit ced7e881b9
5 changed files with 384 additions and 7 deletions

View file

@ -7,6 +7,7 @@ import time
import struct
import sqlite3
import random
import shlex
import RNS.vendor.umsgpack as msgpack
import RNS.Interfaces.Interface as Interface
@ -16,6 +17,7 @@ import multiprocessing.connection
from threading import Lock
from .res import sideband_fb_data
from .sense import Telemeter, Commands
from .plugins import SidebandCommandPlugin, SidebandServicePlugin
if RNS.vendor.platformutils.get_platform() == "android":
from jnius import autoclass, cast
@ -243,6 +245,11 @@ class SidebandCore():
RNS.Transport.register_announce_handler(self)
RNS.Transport.register_announce_handler(self.propagation_detector)
self.active_command_plugins = {}
self.active_service_plugins = {}
if self.is_service or self.is_standalone:
self.__load_plugins()
def clear_tmp_dir(self):
if os.path.isdir(self.tmp_dir):
for file in os.listdir(self.tmp_dir):
@ -591,6 +598,13 @@ class SidebandCore():
if not "telemetry_s_information_text" in self.config:
self.config["telemetry_s_information_text"] = ""
if not "service_plugins_enabled" in self.config:
self.config["service_plugins_enabled"] = False
if not "command_plugins_enabled" in self.config:
self.config["command_plugins_enabled"] = False
if not "command_plugins_path" in self.config:
self.config["command_plugins_path"] = None
if not "map_history_limit" in self.config:
self.config["map_history_limit"] = 7*24*60*60
if not "map_lat" in self.config:
@ -656,6 +670,58 @@ class SidebandCore():
if self.is_client:
self.setstate("wants.settings_reload", True)
def __load_plugins(self):
plugins_path = self.config["command_plugins_path"]
command_plugins_enabled = self.config["command_plugins_enabled"] == True
service_plugins_enabled = self.config["service_plugins_enabled"] == True
plugins_enabled = service_plugins_enabled
if plugins_enabled:
if plugins_path != None:
if os.path.isdir(plugins_path):
for file in os.listdir(plugins_path):
if file.lower().endswith(".py"):
plugin_globals = {}
plugin_globals["SidebandServicePlugin"] = SidebandServicePlugin
plugin_globals["SidebandCommandPlugin"] = SidebandCommandPlugin
RNS.log("Loading plugin \""+str(file)+"\"", RNS.LOG_NOTICE)
plugin_path = os.path.join(plugins_path, file)
exec(open(plugin_path).read(), plugin_globals)
plugin_class = plugin_globals["plugin_class"]
if plugin_class != None:
plugin = plugin_class(self)
plugin.start()
if plugin.is_running():
if issubclass(type(plugin), SidebandCommandPlugin) and command_plugins_enabled:
command_name = plugin.command_name
if not command_name in self.active_command_plugins:
self.active_command_plugins[command_name] = plugin
RNS.log("Registered "+str(plugin)+" as handler for command \""+str(command_name)+"\"", RNS.LOG_NOTICE)
else:
RNS.log("Could not register "+str(plugin)+" as handler for command \""+str(command_name)+"\". Command name was already registered", RNS.LOG_ERROR)
elif issubclass(type(plugin), SidebandServicePlugin):
service_name = plugin.service_name
if not service_name in self.active_service_plugins:
self.active_service_plugins[service_name] = plugin
RNS.log("Registered "+str(plugin)+" for service \""+str(service_name)+"\"", RNS.LOG_NOTICE)
else:
RNS.log("Could not register "+str(plugin)+" for service \""+str(service_name)+"\". Service name was already registered", RNS.LOG_ERROR)
try:
plugin.stop()
except Exception as e:
pass
del plugin
else:
RNS.log("Unknown plugin type was loaded, ignoring it.", RNS.LOG_ERROR)
else:
RNS.log("Plugin "+str(plugin)+" failed to start, ignoring it.", RNS.LOG_ERROR)
del plugin
def reload_configuration(self):
self.__reload_config()
@ -3325,6 +3391,8 @@ class SidebandCore():
commands.append({Commands.SIGNAL_REPORT: True})
elif content.startswith("ping"):
commands.append({Commands.PING: True})
else:
commands.append({Commands.PLUGIN_COMMAND: content})
if len(commands) == 0:
return False
@ -3608,6 +3676,19 @@ class SidebandCore():
except Exception as e:
RNS.log("Error while ingesting LXMF message "+RNS.prettyhexrep(message.hash)+" to database: "+str(e), RNS.LOG_ERROR)
def handle_plugin_command(self, command_string, message):
try:
call = shlex.split(command_string)
command = call[0]
arguments = call[1:]
if command in self.active_command_plugins:
RNS.log("Handling command \""+str(command)+"\" via command plugin "+str(self.active_command_plugins[command]), RNS.LOG_DEBUG)
self.active_command_plugins[command].handle_command(arguments, message)
except Exception as e:
RNS.log("An error occurred while handling a plugin command. The contained exception was: "+str(e), RNS.LOG_ERROR)
RNS.trace_exception(e)
def handle_commands(self, commands, message):
try:
context_dest = message.source_hash
@ -3648,6 +3729,9 @@ class SidebandCore():
self.send_message(phy_str, context_dest, False, skip_fields=True, no_display=True)
elif self.config["command_plugins_enabled"] and Commands.PLUGIN_COMMAND in command:
self.handle_plugin_command(command[Commands.PLUGIN_COMMAND], message)
except Exception as e:
RNS.log("Error while handling commands: "+str(e), RNS.LOG_ERROR)