Add plugin support
This commit is contained in:
parent
5641651c85
commit
ab17e0d198
@ -181,9 +181,13 @@ class API:
|
|||||||
return resp
|
return resp
|
||||||
if not os.environ.get("WERKZEUG_RUN_MAIN") == "true":
|
if not os.environ.get("WERKZEUG_RUN_MAIN") == "true":
|
||||||
logger.info('Starting client on ' + self.host + ':' + str(bindPort) + '...')
|
logger.info('Starting client on ' + self.host + ':' + str(bindPort) + '...')
|
||||||
#logger.debug('Client token: ' + logger.colors.underline + self.clientToken)
|
|
||||||
|
|
||||||
|
try:
|
||||||
app.run(host=self.host, port=bindPort, debug=True, threaded=True)
|
app.run(host=self.host, port=bindPort, debug=True, threaded=True)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(str(e))
|
||||||
|
logger.fatal('Failed to start client on ' + self.host + ':' + str(bindPort) + ', exiting...')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
def validateHost(self, hostType):
|
def validateHost(self, hostType):
|
||||||
'''
|
'''
|
||||||
|
@ -29,12 +29,19 @@ class OnionrCommunicate:
|
|||||||
|
|
||||||
This class handles communication with nodes in the Onionr network.
|
This class handles communication with nodes in the Onionr network.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
self._core = core.Core()
|
self._core = core.Core()
|
||||||
self._utils = onionrutils.OnionrUtils(self._core)
|
self._utils = onionrutils.OnionrUtils(self._core)
|
||||||
self._crypto = onionrcrypto.OnionrCrypto(self._core)
|
self._crypto = onionrcrypto.OnionrCrypto(self._core)
|
||||||
|
|
||||||
|
try:
|
||||||
logger.info('Starting Bitcoin Node... with Tor socks port:' + str(sys.argv[2]))
|
logger.info('Starting Bitcoin Node... with Tor socks port:' + str(sys.argv[2]))
|
||||||
self.bitcoin = btc.OnionrBTC(torP=int(sys.argv[2]))
|
self.bitcoin = btc.OnionrBTC(torP=int(sys.argv[2]))
|
||||||
logger.info('Bitcoin Node started, on block: ' + self.bitcoin.node.getBlockHash(self.bitcoin.node.getLastBlockHeight()))
|
logger.info('Bitcoin Node started, on block: ' + self.bitcoin.node.getBlockHash(self.bitcoin.node.getLastBlockHeight()))
|
||||||
|
except:
|
||||||
|
logger.fatal('Failed to start Bitcoin Node, exiting...')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
blockProcessTimer = 0
|
blockProcessTimer = 0
|
||||||
blockProcessAmount = 5
|
blockProcessAmount = 5
|
||||||
heartBeatTimer = 0
|
heartBeatTimer = 0
|
||||||
@ -48,6 +55,10 @@ class OnionrCommunicate:
|
|||||||
|
|
||||||
if os.path.exists(self._core.queueDB):
|
if os.path.exists(self._core.queueDB):
|
||||||
self._core.clearDaemonQueue()
|
self._core.clearDaemonQueue()
|
||||||
|
|
||||||
|
# Loads in and starts the enabled plugins
|
||||||
|
plugins.reload()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
command = self._core.daemonQueue()
|
command = self._core.daemonQueue()
|
||||||
# Process blocks based on a timer
|
# Process blocks based on a timer
|
||||||
@ -63,7 +74,6 @@ class OnionrCommunicate:
|
|||||||
self.lookupBlocks()
|
self.lookupBlocks()
|
||||||
self.processBlocks()
|
self.processBlocks()
|
||||||
blockProcessTimer = 0
|
blockProcessTimer = 0
|
||||||
#logger.debug('Communicator daemon heartbeat')
|
|
||||||
if command != False:
|
if command != False:
|
||||||
if command[0] == 'shutdown':
|
if command[0] == 'shutdown':
|
||||||
logger.warn('Daemon recieved exit command.')
|
logger.warn('Daemon recieved exit command.')
|
||||||
@ -76,12 +86,14 @@ class OnionrCommunicate:
|
|||||||
'''
|
'''
|
||||||
Get new peers
|
Get new peers
|
||||||
'''
|
'''
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def lookupBlocks(self):
|
def lookupBlocks(self):
|
||||||
'''
|
'''
|
||||||
Lookup blocks and merge new ones
|
Lookup blocks and merge new ones
|
||||||
'''
|
'''
|
||||||
|
|
||||||
peerList = self._core.listAdders()
|
peerList = self._core.listAdders()
|
||||||
blocks = ''
|
blocks = ''
|
||||||
for i in peerList:
|
for i in peerList:
|
||||||
@ -126,6 +138,7 @@ class OnionrCommunicate:
|
|||||||
|
|
||||||
This is meant to be called from the communicator daemon on its timer.
|
This is meant to be called from the communicator daemon on its timer.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
for i in self._core.getBlockList(True).split("\n"):
|
for i in self._core.getBlockList(True).split("\n"):
|
||||||
if i != "":
|
if i != "":
|
||||||
logger.warn('UNSAVED BLOCK: ' + i)
|
logger.warn('UNSAVED BLOCK: ' + i)
|
||||||
@ -137,6 +150,7 @@ class OnionrCommunicate:
|
|||||||
'''
|
'''
|
||||||
Download a block from random order of peers
|
Download a block from random order of peers
|
||||||
'''
|
'''
|
||||||
|
|
||||||
peerList = self._core.listAdders()
|
peerList = self._core.listAdders()
|
||||||
blocks = ''
|
blocks = ''
|
||||||
for i in peerList:
|
for i in peerList:
|
||||||
@ -164,12 +178,14 @@ class OnionrCommunicate:
|
|||||||
'''
|
'''
|
||||||
URL encodes the data
|
URL encodes the data
|
||||||
'''
|
'''
|
||||||
|
|
||||||
return urllib.parse.quote_plus(data)
|
return urllib.parse.quote_plus(data)
|
||||||
|
|
||||||
def performGet(self, action, peer, data=None, peerType='tor'):
|
def performGet(self, action, peer, data=None, peerType='tor'):
|
||||||
'''
|
'''
|
||||||
Performs a request to a peer through Tor or i2p (currently only Tor)
|
Performs a request to a peer through Tor or i2p (currently only Tor)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if not peer.endswith('.onion') and not peer.endswith('.onion/'):
|
if not peer.endswith('.onion') and not peer.endswith('.onion/'):
|
||||||
raise PeerError('Currently only Tor .onion peers are supported. You must manually specify .onion')
|
raise PeerError('Currently only Tor .onion peers are supported. You must manually specify .onion')
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ def get(key, default = None):
|
|||||||
'''
|
'''
|
||||||
Gets the key from configuration, or returns `default`
|
Gets the key from configuration, or returns `default`
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if is_set(key):
|
if is_set(key):
|
||||||
return get_config()[key]
|
return get_config()[key]
|
||||||
return default
|
return default
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
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 sys, os, base64, random, getpass, shutil, subprocess, requests, time, platform
|
import sys, os, base64, random, getpass, shutil, subprocess, requests, time, platform
|
||||||
import api, core, gui, config, logger
|
import api, core, gui, config, logger, onionrplugins as plugins
|
||||||
from onionrutils import OnionrUtils
|
from onionrutils import OnionrUtils
|
||||||
from netcontroller import NetController
|
from netcontroller import NetController
|
||||||
|
|
||||||
@ -130,26 +130,44 @@ class Onionr:
|
|||||||
|
|
||||||
def getCommands(self):
|
def getCommands(self):
|
||||||
return {
|
return {
|
||||||
|
'': self.showHelpSuggestion,
|
||||||
'help': self.showHelp,
|
'help': self.showHelp,
|
||||||
'version': self.version,
|
'version': self.version,
|
||||||
'config': self.configure,
|
'config': self.configure,
|
||||||
'start': self.start,
|
'start': self.start,
|
||||||
'stop': self.killDaemon,
|
'stop': self.killDaemon,
|
||||||
'stats': self.showStats,
|
'stats': self.showStats,
|
||||||
|
|
||||||
|
'enable-plugin': self.enablePlugin,
|
||||||
|
'enplugin': self.enablePlugin,
|
||||||
|
'enableplugin': self.enablePlugin,
|
||||||
|
'enmod': self.enablePlugin,
|
||||||
|
'disable-plugin': self.disablePlugin,
|
||||||
|
'displugin': self.disablePlugin,
|
||||||
|
'disableplugin': self.disablePlugin,
|
||||||
|
'dismod': self.disablePlugin,
|
||||||
|
'reload-plugin': self.reloadPlugin,
|
||||||
|
'reloadplugin': self.reloadPlugin,
|
||||||
|
'reload-plugins': self.reloadPlugin,
|
||||||
|
'reloadplugins': self.reloadPlugin,
|
||||||
|
|
||||||
'listpeers': self.listPeers,
|
'listpeers': self.listPeers,
|
||||||
'list-peers': self.listPeers,
|
'list-peers': self.listPeers,
|
||||||
'': self.showHelpSuggestion,
|
|
||||||
'addmsg': self.addMessage,
|
'addmsg': self.addMessage,
|
||||||
'addmessage': self.addMessage,
|
'addmessage': self.addMessage,
|
||||||
'add-msg': self.addMessage,
|
'add-msg': self.addMessage,
|
||||||
'add-message': self.addMessage,
|
'add-message': self.addMessage,
|
||||||
'pm': self.sendEncrypt,
|
'pm': self.sendEncrypt,
|
||||||
|
|
||||||
'gui': self.openGUI,
|
'gui': self.openGUI,
|
||||||
|
|
||||||
'addpeer': self.addPeer,
|
'addpeer': self.addPeer,
|
||||||
'add-peer': self.addPeer,
|
'add-peer': self.addPeer,
|
||||||
'add-address': self.addAddress,
|
'add-address': self.addAddress,
|
||||||
'connect': self.addAddress,
|
'addaddress': self.addAddress,
|
||||||
'addaddress': self.addAddress
|
|
||||||
|
'connect': self.addAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
def getHelp(self):
|
def getHelp(self):
|
||||||
@ -160,10 +178,13 @@ class Onionr:
|
|||||||
'start': 'Starts the Onionr daemon',
|
'start': 'Starts the Onionr daemon',
|
||||||
'stop': 'Stops the Onionr daemon',
|
'stop': 'Stops the Onionr daemon',
|
||||||
'stats': 'Displays node statistics',
|
'stats': 'Displays node statistics',
|
||||||
'list-peers': 'Displays a list of peers (?)',
|
'enable-plugin': 'Enables and starts a plugin',
|
||||||
|
'disable-plugin': 'Disables and stops a plugin',
|
||||||
|
'reload-plugin': 'Reloads a plugin',
|
||||||
|
'list-peers': 'Displays a list of peers',
|
||||||
'add-peer': 'Adds a peer (?)',
|
'add-peer': 'Adds a peer (?)',
|
||||||
'add-msg': 'Broadcasts a message to the Onionr network',
|
'add-msg': 'Broadcasts a message to the Onionr network',
|
||||||
'pm': 'Adds a private message (?)',
|
'pm': 'Adds a private message to block',
|
||||||
'gui': 'Opens a graphical interface for Onionr'
|
'gui': 'Opens a graphical interface for Onionr'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,6 +285,8 @@ class Onionr:
|
|||||||
logger.info("Adding peer: " + logger.colors.underline + newPeer)
|
logger.info("Adding peer: " + logger.colors.underline + newPeer)
|
||||||
self.onionrCore.addPeer(newPeer)
|
self.onionrCore.addPeer(newPeer)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def addAddress(self):
|
def addAddress(self):
|
||||||
'''Adds a Onionr node address'''
|
'''Adds a Onionr node address'''
|
||||||
try:
|
try:
|
||||||
@ -277,6 +300,8 @@ class Onionr:
|
|||||||
else:
|
else:
|
||||||
logger.warn("Unable to add address")
|
logger.warn("Unable to add address")
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def addMessage(self):
|
def addMessage(self):
|
||||||
'''
|
'''
|
||||||
Broadcasts a message to the Onionr network
|
Broadcasts a message to the Onionr network
|
||||||
@ -291,6 +316,52 @@ class Onionr:
|
|||||||
self.onionrCore.addToBlockDB(addedHash, selfInsert=True)
|
self.onionrCore.addToBlockDB(addedHash, selfInsert=True)
|
||||||
self.onionrCore.setBlockType(addedHash, 'txt')
|
self.onionrCore.setBlockType(addedHash, 'txt')
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def enablePlugin(self):
|
||||||
|
'''
|
||||||
|
Enables and starts the given plugin
|
||||||
|
'''
|
||||||
|
|
||||||
|
if len(sys.argv) >= 3:
|
||||||
|
plugin_name = sys.argv[2]
|
||||||
|
logger.info('Enabling plugin \"' + plugin_name + '\"...')
|
||||||
|
plugins.enable(plugin_name)
|
||||||
|
else:
|
||||||
|
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin>')
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def disablePlugin(self):
|
||||||
|
'''
|
||||||
|
Disables and stops the given plugin
|
||||||
|
'''
|
||||||
|
|
||||||
|
if len(sys.argv) >= 3:
|
||||||
|
plugin_name = sys.argv[2]
|
||||||
|
logger.info('Disabling plugin \"' + plugin_name + '\"...')
|
||||||
|
plugins.disable(plugin_name)
|
||||||
|
else:
|
||||||
|
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin>')
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def reloadPlugin(self):
|
||||||
|
'''
|
||||||
|
Reloads (stops and starts) all plugins, or the given plugin
|
||||||
|
'''
|
||||||
|
|
||||||
|
if len(sys.argv) >= 3:
|
||||||
|
plugin_name = sys.argv[2]
|
||||||
|
logger.info('Reloading plugin \"' + plugin_name + '\"...')
|
||||||
|
plugins.stop(plugin_name)
|
||||||
|
plugins.start(plugin_name)
|
||||||
|
else:
|
||||||
|
logger.info('Reloading all plugins...')
|
||||||
|
plugins.reload()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def notFound(self):
|
def notFound(self):
|
||||||
'''
|
'''
|
||||||
Displays a "command not found" message
|
Displays a "command not found" message
|
||||||
@ -325,6 +396,7 @@ class Onionr:
|
|||||||
'''
|
'''
|
||||||
Starts the Onionr communication daemon
|
Starts the Onionr communication daemon
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if not os.environ.get("WERKZEUG_RUN_MAIN") == "true":
|
if not os.environ.get("WERKZEUG_RUN_MAIN") == "true":
|
||||||
if self._developmentMode:
|
if self._developmentMode:
|
||||||
logger.warn('DEVELOPMENT MODE ENABLED (THIS IS LESS SECURE!)')
|
logger.warn('DEVELOPMENT MODE ENABLED (THIS IS LESS SECURE!)')
|
||||||
|
53
onionr/onionrevents.py
Normal file
53
onionr/onionrevents.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
'''
|
||||||
|
Onionr - P2P Microblogging Platform & Social network
|
||||||
|
|
||||||
|
This file deals with configuration management.
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
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 config, logger, onionrplugins as plugins
|
||||||
|
|
||||||
|
def event(event_name, data = None, onionr = None):
|
||||||
|
'''
|
||||||
|
Calls an event on all plugins (if defined)
|
||||||
|
'''
|
||||||
|
|
||||||
|
for plugin in plugins.get_enabled_plugins():
|
||||||
|
try:
|
||||||
|
call(plugins.get_plugin(plugin), event_name, data, onionr)
|
||||||
|
except:
|
||||||
|
logger.warn('Event \"' + event_name + '\" failed for plugin \"' + plugin + '\".')
|
||||||
|
|
||||||
|
def call(plugin, event_name, data = None, onionr = None):
|
||||||
|
'''
|
||||||
|
Calls an event on a plugin if one is defined
|
||||||
|
'''
|
||||||
|
|
||||||
|
if not plugin is None:
|
||||||
|
try:
|
||||||
|
attribute = 'on_' + str(event_name).lower()
|
||||||
|
|
||||||
|
# TODO: Use multithreading perhaps?
|
||||||
|
if hasattr(plugin, attribute):
|
||||||
|
logger.debug('Calling event ' + str(event_name))
|
||||||
|
getattr(plugin, attribute)(onionr, data)
|
||||||
|
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
logger.warn('Failed to call event ' + str(event_name) + ' on module.')
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
231
onionr/onionrplugins.py
Normal file
231
onionr/onionrplugins.py
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
'''
|
||||||
|
Onionr - P2P Microblogging Platform & Social network
|
||||||
|
|
||||||
|
This file deals with management of modules/plugins.
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
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 os, re, importlib, config, logger
|
||||||
|
import onionrevents as events
|
||||||
|
|
||||||
|
_pluginsfolder = 'data/plugins/'
|
||||||
|
_instances = dict()
|
||||||
|
|
||||||
|
def reload(stop_event = True):
|
||||||
|
'''
|
||||||
|
Reloads all the plugins
|
||||||
|
'''
|
||||||
|
|
||||||
|
check()
|
||||||
|
|
||||||
|
try:
|
||||||
|
enabled_plugins = get_enabled_plugins()
|
||||||
|
|
||||||
|
if stop_event is True:
|
||||||
|
logger.debug('Reloading all plugins...')
|
||||||
|
else:
|
||||||
|
logger.debug('Loading all plugins...')
|
||||||
|
|
||||||
|
if stop_event is True:
|
||||||
|
for plugin in enabled_plugins:
|
||||||
|
stop(plugin)
|
||||||
|
|
||||||
|
for plugin in enabled_plugins:
|
||||||
|
start(plugin)
|
||||||
|
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
logger.error('Failed to reload plugins.')
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def enable(name, start_event = True):
|
||||||
|
'''
|
||||||
|
Enables a plugin
|
||||||
|
'''
|
||||||
|
|
||||||
|
check()
|
||||||
|
|
||||||
|
if exists(name):
|
||||||
|
enabled_plugins = get_enabled_plugins()
|
||||||
|
enabled_plugins.append(name)
|
||||||
|
config_plugins = config.get('plugins')
|
||||||
|
config_plugins['enabled'] = enabled_plugins
|
||||||
|
config.set('plugins', config_plugins, True)
|
||||||
|
|
||||||
|
events.call(get_plugin(name), 'enable')
|
||||||
|
|
||||||
|
if start_event is True:
|
||||||
|
start(name)
|
||||||
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logger.error('Failed to enable plugin \"' + name + '\", disabling plugin.')
|
||||||
|
disable(name)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def disable(name, stop_event = True):
|
||||||
|
'''
|
||||||
|
Disables a plugin
|
||||||
|
'''
|
||||||
|
|
||||||
|
check()
|
||||||
|
|
||||||
|
if is_enabled(name):
|
||||||
|
enabled_plugins = get_enabled_plugins()
|
||||||
|
enabled_plugins.remove(name)
|
||||||
|
config_plugins = config.get('plugins')
|
||||||
|
config_plugins['enabled'] = enabled_plugins
|
||||||
|
config.set('plugins', config_plugins, True)
|
||||||
|
|
||||||
|
if exists(name):
|
||||||
|
events.call(get_plugin(name), 'disable')
|
||||||
|
|
||||||
|
if stop_event is True:
|
||||||
|
stop(name)
|
||||||
|
|
||||||
|
def start(name):
|
||||||
|
'''
|
||||||
|
Starts the plugin
|
||||||
|
'''
|
||||||
|
|
||||||
|
check()
|
||||||
|
|
||||||
|
if exists(name):
|
||||||
|
try:
|
||||||
|
plugin = get_plugin(name)
|
||||||
|
|
||||||
|
if plugin is None:
|
||||||
|
raise Exception('Failed to import module.')
|
||||||
|
else:
|
||||||
|
events.call(plugin, 'start')
|
||||||
|
|
||||||
|
return plugin
|
||||||
|
except:
|
||||||
|
logger.error('Failed to start module \"' + name + '\".')
|
||||||
|
else:
|
||||||
|
logger.error('Failed to start nonexistant module \"' + name + '\".')
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def stop(name):
|
||||||
|
'''
|
||||||
|
Stops the plugin
|
||||||
|
'''
|
||||||
|
|
||||||
|
check()
|
||||||
|
|
||||||
|
if exists(name):
|
||||||
|
try:
|
||||||
|
plugin = get_plugin(name)
|
||||||
|
|
||||||
|
if plugin is None:
|
||||||
|
raise Exception('Failed to import module.')
|
||||||
|
else:
|
||||||
|
events.call(plugin, 'stop')
|
||||||
|
|
||||||
|
return plugin
|
||||||
|
except:
|
||||||
|
logger.error('Failed to stop module \"' + name + '\".')
|
||||||
|
else:
|
||||||
|
logger.error('Failed to stop nonexistant module \"' + name + '\".')
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_plugin(name):
|
||||||
|
'''
|
||||||
|
Returns the instance of a module
|
||||||
|
'''
|
||||||
|
|
||||||
|
check()
|
||||||
|
|
||||||
|
if str(name).lower() in _instances:
|
||||||
|
return _instances[str(name).lower()]
|
||||||
|
else:
|
||||||
|
_instances[str(name).lower()] = importlib.import_module(get_plugins_folder(name, False).replace('/', '.') + 'main')
|
||||||
|
return get_plugin(name)
|
||||||
|
|
||||||
|
def get_plugins():
|
||||||
|
'''
|
||||||
|
Returns a list of plugins (deprecated)
|
||||||
|
'''
|
||||||
|
|
||||||
|
return _instances
|
||||||
|
|
||||||
|
def exists(name):
|
||||||
|
'''
|
||||||
|
Return value indicates whether or not the plugin exists
|
||||||
|
'''
|
||||||
|
|
||||||
|
check()
|
||||||
|
|
||||||
|
return os.path.isdir(get_plugins_folder(str(name).lower()))
|
||||||
|
|
||||||
|
def get_enabled_plugins():
|
||||||
|
'''
|
||||||
|
Returns a list of the enabled plugins
|
||||||
|
'''
|
||||||
|
|
||||||
|
check()
|
||||||
|
|
||||||
|
config.reload()
|
||||||
|
|
||||||
|
return config.get('plugins')['enabled']
|
||||||
|
|
||||||
|
def is_enabled(name):
|
||||||
|
'''
|
||||||
|
Return value indicates whether or not the plugin is enabled
|
||||||
|
'''
|
||||||
|
|
||||||
|
return name in get_enabled_plugins()
|
||||||
|
|
||||||
|
def get_plugins_folder(name = None, absolute = True):
|
||||||
|
'''
|
||||||
|
Returns the path to the plugins folder
|
||||||
|
'''
|
||||||
|
|
||||||
|
path = ''
|
||||||
|
|
||||||
|
if name is None:
|
||||||
|
path = _pluginsfolder
|
||||||
|
else:
|
||||||
|
# only allow alphanumeric characters
|
||||||
|
path = _pluginsfolder + re.sub('[^0-9a-zA-Z]+', '', str(name).lower()) + '/'
|
||||||
|
|
||||||
|
if absolute is True:
|
||||||
|
path = os.path.abspath(path)
|
||||||
|
|
||||||
|
return path
|
||||||
|
|
||||||
|
def check():
|
||||||
|
'''
|
||||||
|
Checks to make sure files exist
|
||||||
|
'''
|
||||||
|
|
||||||
|
config.reload()
|
||||||
|
|
||||||
|
if not config.is_set('plugins'):
|
||||||
|
logger.debug('Generating plugin config data...')
|
||||||
|
config.set('plugins', {'enabled': []}, True)
|
||||||
|
|
||||||
|
if not os.path.exists(os.path.dirname(get_plugins_folder())):
|
||||||
|
logger.debug('Generating plugin data folder...')
|
||||||
|
os.path.mkdirs(os.path.dirname(get_plugins_folder()))
|
||||||
|
|
||||||
|
return
|
Loading…
Reference in New Issue
Block a user