Add in PluginAPI (#7)

* Modify soft resetting

Made it more like hard resetting (output-wise).

* Refactor timedHmac.py

* Update onionrplugins.py

Remove test code

* Create onionrpluginapi.py

* Update onionrevents.py

* Update onionrpluginapi.py

* Update onionrevents.py

* Update onionr.py

* Add onionr object to events

* Update onionr.py
This commit is contained in:
20esaua 2018-04-20 18:20:26 -07:00 committed by Arinerron
parent 034410a6e8
commit 2126138428
6 changed files with 198 additions and 37 deletions

View File

@ -23,11 +23,11 @@ test:
@mv onionr/data-backup onionr/data | true > /dev/null 2>&1 @mv onionr/data-backup onionr/data | true > /dev/null 2>&1
soft-reset: soft-reset:
rm -f onionr/data/blocks/*.dat | true > /dev/null 2>&1 @echo "Soft-resetting Onionr..."
rm -f onionr/data/*.db | true > /dev/null 2>&1 rm -f onionr/data/blocks/*.dat onionr/data/*.db | true > /dev/null 2>&1
@./RUN-LINUX.sh version | grep -v "Failed" --color=always
reset: reset:
@echo "Hard-resetting Onionr..." @echo "Hard-resetting Onionr..."
rm -rf onionr/data/ | true > /dev/null 2>&1 rm -rf onionr/data/ | true > /dev/null 2>&1
@./RUN-LINUX.sh version | grep -v "Failed" --color=always @./RUN-LINUX.sh version | grep -v "Failed" --color=always

View File

@ -41,9 +41,6 @@ ONIONR_VERSION = '0.0.0' # for debugging and stuff
API_VERSION = '1' # increments of 1; only change when something fundemental about how the API works changes. This way other nodes knows how to communicate without learning too much information about you. API_VERSION = '1' # increments of 1; only change when something fundemental about how the API works changes. This way other nodes knows how to communicate without learning too much information about you.
class Onionr: class Onionr:
cmds = {}
cmdhelp = {}
def __init__(self): def __init__(self):
''' '''
Main Onionr class. This is for the CLI program, and does not handle much of the logic. Main Onionr class. This is for the CLI program, and does not handle much of the logic.
@ -210,10 +207,16 @@ class Onionr:
return self.cmdhelp return self.cmdhelp
def addCommand(self, command, function): def addCommand(self, command, function):
cmds[str(command).lower()] = function self.cmds[str(command).lower()] = function
def addHelp(self, command, description): def addHelp(self, command, description):
cmdhelp[str(command).lower()] = str(description) self.cmdhelp[str(command).lower()] = str(description)
def delCommand(self, command):
return self.cmds.pop(str(command).lower(), None)
def delHelp(self, command):
return self.cmdhelp.pop(str(command).lower(), None)
def configure(self): def configure(self):
''' '''
@ -243,6 +246,8 @@ class Onionr:
command = commands.get(argument, self.notFound) command = commands.get(argument, self.notFound)
command() command()
return
''' '''
THIS SECTION DEFINES THE COMMANDS THIS SECTION DEFINES THE COMMANDS
@ -257,6 +262,8 @@ class Onionr:
logger.info(ONIONR_TAGLINE) logger.info(ONIONR_TAGLINE)
if verbosity >= 2: if verbosity >= 2:
logger.info('Running on ' + platform.platform() + ' ' + platform.release()) logger.info('Running on ' + platform.platform() + ' ' + platform.release())
return
def sendEncrypt(self): def sendEncrypt(self):
''' '''
@ -362,7 +369,7 @@ class Onionr:
if len(sys.argv) >= 3: if len(sys.argv) >= 3:
plugin_name = sys.argv[2] plugin_name = sys.argv[2]
logger.info('Enabling plugin \"' + plugin_name + '\"...') logger.info('Enabling plugin \"' + plugin_name + '\"...')
plugins.enable(plugin_name) plugins.enable(plugin_name, self)
else: else:
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin>') logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin>')
@ -376,7 +383,7 @@ class Onionr:
if len(sys.argv) >= 3: if len(sys.argv) >= 3:
plugin_name = sys.argv[2] plugin_name = sys.argv[2]
logger.info('Disabling plugin \"' + plugin_name + '\"...') logger.info('Disabling plugin \"' + plugin_name + '\"...')
plugins.disable(plugin_name) plugins.disable(plugin_name, self)
else: else:
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin>') logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin>')
@ -390,11 +397,11 @@ class Onionr:
if len(sys.argv) >= 3: if len(sys.argv) >= 3:
plugin_name = sys.argv[2] plugin_name = sys.argv[2]
logger.info('Reloading plugin \"' + plugin_name + '\"...') logger.info('Reloading plugin \"' + plugin_name + '\"...')
plugins.stop(plugin_name) plugins.stop(plugin_name, self)
plugins.start(plugin_name) plugins.start(plugin_name, self)
else: else:
logger.info('Reloading all plugins...') logger.info('Reloading all plugins...')
plugins.reload() plugins.reload(self)
return return

View File

@ -18,7 +18,10 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
''' '''
import config, logger, onionrplugins as plugins import config, logger, onionrplugins as plugins, onionrpluginapi as pluginapi
def get_pluginapi(onionr):
return pluginapi.PluginAPI(onionr)
def event(event_name, data = None, onionr = None): def event(event_name, data = None, onionr = None):
''' '''
@ -27,11 +30,11 @@ def event(event_name, data = None, onionr = None):
for plugin in plugins.get_enabled_plugins(): for plugin in plugins.get_enabled_plugins():
try: try:
call(plugins.get_plugin(plugin), event_name, data, onionr) call(plugins.get_plugin(plugin), event_name, data, self.get_pluginapi(onionr))
except: except:
logger.warn('Event \"' + event_name + '\" failed for plugin \"' + plugin + '\".') logger.warn('Event \"' + event_name + '\" failed for plugin \"' + plugin + '\".')
def call(plugin, event_name, data = None, onionr = None): def call(plugin, event_name, data = None, pluginapi = None):
''' '''
Calls an event on a plugin if one is defined Calls an event on a plugin if one is defined
''' '''
@ -43,7 +46,7 @@ def call(plugin, event_name, data = None, onionr = None):
# TODO: Use multithreading perhaps? # TODO: Use multithreading perhaps?
if hasattr(plugin, attribute): if hasattr(plugin, attribute):
logger.debug('Calling event ' + str(event_name)) logger.debug('Calling event ' + str(event_name))
getattr(plugin, attribute)(onionr, data) getattr(plugin, attribute)(pluginapi, data)
return True return True
except: except:

150
onionr/onionrpluginapi.py Normal file
View File

@ -0,0 +1,150 @@
'''
Onionr - P2P Microblogging Platform & Social network
This file deals with the object that is passed with each event
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import onionrplugins as plugins, logger
class PluginAPI:
def __init__(self, onionr):
self.onionr = onionr
self.daemon = DaemonAPI(self)
self.plugin = PluginAPI(self)
self.command = CommandAPI(self)
def get_onionr(self):
return self.onionr
def get_core(self):
return self.get_onionr().onionrCore
def get_utils(self):
return self.get_onionr().onionrUtils
def get_daemonapi(self):
return self.daemon
def get_pluginapi(self):
return self.plugin
def get_commandapi(self):
return self.command
def is_development_mode(self):
return self.get_onionr()._developmentMode
class DaemonAPI:
def __init__(self, pluginapi):
self.pluginapi = pluginapi
def start(self):
self.pluginapi.get_onionr().daemon()
return
def stop(self):
self.pluginapi.get_onionr().killDaemon()
return
def queue(self, command, data = ''):
self.pluginapi.get_core().daemonQueueAdd(command, data)
return
def local_command(self, command):
self.pluginapi.get_utils().localCommand(self, command)
return
def queue_pop(self):
return self.get_core().daemonQueue()
class PluginAPI:
def __init__(self, pluginapi):
self.pluginapi = pluginapi
def start(self, name):
plugins.start(name)
def stop(self, name):
plugins.stop(name)
def reload(self, name):
plugins.reload(name)
def enable(self, name):
plugins.enable(name)
def disable(self, name):
plugins.disable(name)
def is_enabled(self, name):
return plugins.is_enabled(name)
def get_enabled_plugins(self):
return plugins.get_enabled_plugins()
class CommandAPI:
def __init__(self, pluginapi):
self.pluginapi = pluginapi
def register(self, names, call = None):
if isinstance(names, str):
names = [names]
for name in names:
self.pluginapi.get_onionr().addCommand(name, call)
return
def unregister(self, names):
if isinstance(names, str):
names = [names]
for name in names:
self.pluginapi.get_onionr().delCommand(name)
return
def register_help(self, names, description):
if isinstance(names, str):
names = [names]
for name in names:
self.pluginapi.get_onionr().addHelp(name, description)
return
def unregister_help(self, names):
if isinstance(names, str):
names = [names]
for name in names:
self.pluginapi.get_onionr().delHelp(name)
return
def call(self, name):
self.pluginapi.get_onionr().execute(name)
return
def get_commands(self):
return self.pluginapi.get_onionr().getCommands()

View File

@ -24,7 +24,7 @@ import onionrevents as events
_pluginsfolder = 'data/plugins/' _pluginsfolder = 'data/plugins/'
_instances = dict() _instances = dict()
def reload(stop_event = True): def reload(onionr = None, stop_event = True):
''' '''
Reloads all the plugins Reloads all the plugins
''' '''
@ -41,10 +41,10 @@ def reload(stop_event = True):
if stop_event is True: if stop_event is True:
for plugin in enabled_plugins: for plugin in enabled_plugins:
stop(plugin) stop(plugin, onionr)
for plugin in enabled_plugins: for plugin in enabled_plugins:
start(plugin) start(plugin, onionr)
return True return True
except: except:
@ -53,7 +53,7 @@ def reload(stop_event = True):
return False return False
def enable(name, start_event = True): def enable(name, onionr = None, start_event = True):
''' '''
Enables a plugin Enables a plugin
''' '''
@ -67,7 +67,7 @@ def enable(name, start_event = True):
config_plugins['enabled'] = enabled_plugins config_plugins['enabled'] = enabled_plugins
config.set('plugins', config_plugins, True) config.set('plugins', config_plugins, True)
events.call(get_plugin(name), 'enable') events.call(get_plugin(name), 'enable', onionr)
if start_event is True: if start_event is True:
start(name) start(name)
@ -80,7 +80,7 @@ def enable(name, start_event = True):
return False return False
def disable(name, stop_event = True): def disable(name, onionr = None, stop_event = True):
''' '''
Disables a plugin Disables a plugin
''' '''
@ -95,12 +95,12 @@ def disable(name, stop_event = True):
config.set('plugins', config_plugins, True) config.set('plugins', config_plugins, True)
if exists(name): if exists(name):
events.call(get_plugin(name), 'disable') events.call(get_plugin(name), 'disable', onionr)
if stop_event is True: if stop_event is True:
stop(name) stop(name)
def start(name): def start(name, onionr = None):
''' '''
Starts the plugin Starts the plugin
''' '''
@ -114,7 +114,7 @@ def start(name):
if plugin is None: if plugin is None:
raise Exception('Failed to import module.') raise Exception('Failed to import module.')
else: else:
events.call(plugin, 'start') events.call(plugin, 'start', onionr)
return plugin return plugin
except: except:
@ -124,7 +124,7 @@ def start(name):
return None return None
def stop(name): def stop(name, onionr = None):
''' '''
Stops the plugin Stops the plugin
''' '''
@ -138,7 +138,7 @@ def stop(name):
if plugin is None: if plugin is None:
raise Exception('Failed to import module.') raise Exception('Failed to import module.')
else: else:
events.call(plugin, 'stop') events.call(plugin, 'stop', onionr)
return plugin return plugin
except: except:
@ -225,10 +225,5 @@ def check():
if not os.path.exists(os.path.dirname(get_plugins_folder())): if not os.path.exists(os.path.dirname(get_plugins_folder())):
logger.debug('Generating plugin data folder...') logger.debug('Generating plugin data folder...')
os.makedirs(os.path.dirname(get_plugins_folder())) os.makedirs(os.path.dirname(get_plugins_folder()))
#if not exists('test'):
#os.makedirs(get_plugins_folder('test'))
#with open(get_plugins_folder('test') + '/main.py', 'a') as main:
#main.write("print('Running')\n\ndef on_test(onionr = None, data = None):\n print('received test event!')\n return True\n\ndef on_start(onionr = None, data = None):\n print('start event called')\n\ndef on_stop(onionr = None, data = None):\n print('stop event called')\n\ndef on_enable(onionr = None, data = None):\n print('enable event called')\n\ndef on_disable(onionr = None, data = None):\n print('disable event called')\n")
#enable('test')
return return

View File

@ -12,7 +12,9 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
''' '''
import hmac, base64, time, math import hmac, base64, time, math
class TimedHMAC: class TimedHMAC:
def __init__(self, base64Key, data, hashAlgo): def __init__(self, base64Key, data, hashAlgo):
''' '''
@ -23,6 +25,7 @@ class TimedHMAC:
Maximum of 10 seconds grace period Maximum of 10 seconds grace period
''' '''
self.data = data self.data = data
self.expire = math.floor(time.time()) self.expire = math.floor(time.time())
self.hashAlgo = hashAlgo self.hashAlgo = hashAlgo
@ -34,11 +37,14 @@ class TimedHMAC:
return return
def check(self, data): def check(self, data):
# Check a hash (and verify time is sane) '''
Check a hash (and verify time is sane)
'''
testHash = hmac.HMAC(base64.b64decode(base64Key).decode(), digestmod=self.hashAlgo) testHash = hmac.HMAC(base64.b64decode(base64Key).decode(), digestmod=self.hashAlgo)
testHash.update(data + math.floor(time.time())) testHash.update(data + math.floor(time.time()))
testHash = testHash.hexdigest() testHash = testHash.hexdigest()
if hmac.compare_digest(testHash, self.HMACResult): if hmac.compare_digest(testHash, self.HMACResult):
return true return true
else:
return false return false