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
soft-reset:
rm -f onionr/data/blocks/*.dat | true > /dev/null 2>&1
rm -f onionr/data/*.db | true > /dev/null 2>&1
@echo "Soft-resetting Onionr..."
rm -f onionr/data/blocks/*.dat onionr/data/*.db | true > /dev/null 2>&1
@./RUN-LINUX.sh version | grep -v "Failed" --color=always
reset:
@echo "Hard-resetting Onionr..."
rm -rf onionr/data/ | true > /dev/null 2>&1
@./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.
class Onionr:
cmds = {}
cmdhelp = {}
def __init__(self):
'''
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
def addCommand(self, command, function):
cmds[str(command).lower()] = function
self.cmds[str(command).lower()] = function
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):
'''
@ -244,6 +247,8 @@ class Onionr:
command = commands.get(argument, self.notFound)
command()
return
'''
THIS SECTION DEFINES THE COMMANDS
'''
@ -258,6 +263,8 @@ class Onionr:
if verbosity >= 2:
logger.info('Running on ' + platform.platform() + ' ' + platform.release())
return
def sendEncrypt(self):
'''
Create a private message and send it
@ -362,7 +369,7 @@ class Onionr:
if len(sys.argv) >= 3:
plugin_name = sys.argv[2]
logger.info('Enabling plugin \"' + plugin_name + '\"...')
plugins.enable(plugin_name)
plugins.enable(plugin_name, self)
else:
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin>')
@ -376,7 +383,7 @@ class Onionr:
if len(sys.argv) >= 3:
plugin_name = sys.argv[2]
logger.info('Disabling plugin \"' + plugin_name + '\"...')
plugins.disable(plugin_name)
plugins.disable(plugin_name, self)
else:
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin>')
@ -390,11 +397,11 @@ class Onionr:
if len(sys.argv) >= 3:
plugin_name = sys.argv[2]
logger.info('Reloading plugin \"' + plugin_name + '\"...')
plugins.stop(plugin_name)
plugins.start(plugin_name)
plugins.stop(plugin_name, self)
plugins.start(plugin_name, self)
else:
logger.info('Reloading all plugins...')
plugins.reload()
plugins.reload(self)
return

View File

@ -18,7 +18,10 @@
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):
'''
@ -27,11 +30,11 @@ def event(event_name, data = None, onionr = None):
for plugin in plugins.get_enabled_plugins():
try:
call(plugins.get_plugin(plugin), event_name, data, onionr)
call(plugins.get_plugin(plugin), event_name, data, self.get_pluginapi(onionr))
except:
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
'''
@ -43,7 +46,7 @@ def call(plugin, event_name, data = None, onionr = None):
# TODO: Use multithreading perhaps?
if hasattr(plugin, attribute):
logger.debug('Calling event ' + str(event_name))
getattr(plugin, attribute)(onionr, data)
getattr(plugin, attribute)(pluginapi, data)
return True
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/'
_instances = dict()
def reload(stop_event = True):
def reload(onionr = None, stop_event = True):
'''
Reloads all the plugins
'''
@ -41,10 +41,10 @@ def reload(stop_event = True):
if stop_event is True:
for plugin in enabled_plugins:
stop(plugin)
stop(plugin, onionr)
for plugin in enabled_plugins:
start(plugin)
start(plugin, onionr)
return True
except:
@ -53,7 +53,7 @@ def reload(stop_event = True):
return False
def enable(name, start_event = True):
def enable(name, onionr = None, start_event = True):
'''
Enables a plugin
'''
@ -67,7 +67,7 @@ def enable(name, start_event = True):
config_plugins['enabled'] = enabled_plugins
config.set('plugins', config_plugins, True)
events.call(get_plugin(name), 'enable')
events.call(get_plugin(name), 'enable', onionr)
if start_event is True:
start(name)
@ -80,7 +80,7 @@ def enable(name, start_event = True):
return False
def disable(name, stop_event = True):
def disable(name, onionr = None, stop_event = True):
'''
Disables a plugin
'''
@ -95,12 +95,12 @@ def disable(name, stop_event = True):
config.set('plugins', config_plugins, True)
if exists(name):
events.call(get_plugin(name), 'disable')
events.call(get_plugin(name), 'disable', onionr)
if stop_event is True:
stop(name)
def start(name):
def start(name, onionr = None):
'''
Starts the plugin
'''
@ -114,7 +114,7 @@ def start(name):
if plugin is None:
raise Exception('Failed to import module.')
else:
events.call(plugin, 'start')
events.call(plugin, 'start', onionr)
return plugin
except:
@ -124,7 +124,7 @@ def start(name):
return None
def stop(name):
def stop(name, onionr = None):
'''
Stops the plugin
'''
@ -138,7 +138,7 @@ def stop(name):
if plugin is None:
raise Exception('Failed to import module.')
else:
events.call(plugin, 'stop')
events.call(plugin, 'stop', onionr)
return plugin
except:
@ -226,9 +226,4 @@ def check():
logger.debug('Generating plugin data 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

View File

@ -12,7 +12,9 @@
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 hmac, base64, time, math
class TimedHMAC:
def __init__(self, base64Key, data, hashAlgo):
'''
@ -23,6 +25,7 @@ class TimedHMAC:
Maximum of 10 seconds grace period
'''
self.data = data
self.expire = math.floor(time.time())
self.hashAlgo = hashAlgo
@ -34,11 +37,14 @@ class TimedHMAC:
return
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.update(data + math.floor(time.time()))
testHash = testHash.hexdigest()
if hmac.compare_digest(testHash, self.HMACResult):
return true
else:
return false