See details
- Completes support for repositories - `./RUN-LINUX.sh create-repository [plugins...]` - `./RUN-LINUX.sh add-repository <block hash>` - `./RUN-LINUX.sh remove-repository <block hash>` - Fixes several misc bugs - Refactors code - Some messy code was rewritten - Variables renamed - Migrated old block api (insertBlock) to new Block API (onionrblockapi) - Kept to standards - Made code more reusable in `onionrproofs.py` - Improves logging messages - Added error output for some features missing it - Capitalized sentences - Added punctuation where it is missing - Switched `logger.info` and `logger.debug` in a few places, where it is logical - Removed or added timestamps depending on the circumstance - Added a few misc features - Added command aliases for `add-file` and `import-blocks` - Improved statistics menu - Displays `Known Block Count` - Calculates and displays `Percent Blocks Signed`master
parent
a232e663a7
commit
8846dcc2c6
|
@ -70,7 +70,7 @@ class API:
|
||||||
self.clientToken = config.get('client')['client_hmac']
|
self.clientToken = config.get('client')['client_hmac']
|
||||||
self.timeBypassToken = base64.b16encode(os.urandom(32)).decode()
|
self.timeBypassToken = base64.b16encode(os.urandom(32)).decode()
|
||||||
|
|
||||||
self.i2pEnabled = config.get('i2p')['host']
|
self.i2pEnabled = config.get('i2p', {'host' : False})['host']
|
||||||
|
|
||||||
self.mimeType = 'text/plain'
|
self.mimeType = 'text/plain'
|
||||||
|
|
||||||
|
@ -85,9 +85,9 @@ class API:
|
||||||
self.host = '127.' + str(hostNums[0]) + '.' + str(hostNums[1]) + '.' + str(hostNums[2])
|
self.host = '127.' + str(hostNums[0]) + '.' + str(hostNums[1]) + '.' + str(hostNums[2])
|
||||||
else:
|
else:
|
||||||
self.host = '127.0.0.1'
|
self.host = '127.0.0.1'
|
||||||
hostFile = open('data/host.txt', 'w')
|
|
||||||
hostFile.write(self.host)
|
with open('data/host.txt', 'w') as file:
|
||||||
hostFile.close()
|
file.write(self.host)
|
||||||
|
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def beforeReq():
|
def beforeReq():
|
||||||
|
@ -259,7 +259,7 @@ 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) + '...', timestamp=True)
|
logger.info('Starting client on ' + self.host + ':' + str(bindPort) + '...', timestamp=False)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.http_server = WSGIServer((self.host, bindPort), app)
|
self.http_server = WSGIServer((self.host, bindPort), app)
|
||||||
|
|
|
@ -123,16 +123,16 @@ class OnionrCommunicate:
|
||||||
announceAttempts = 3
|
announceAttempts = 3
|
||||||
announceAttemptCount = 0
|
announceAttemptCount = 0
|
||||||
announceVal = False
|
announceVal = False
|
||||||
logger.info('Announcing node to ' + command[1], timestamp=True)
|
logger.info('Announcing node to %s...' % command[1], timestamp=True)
|
||||||
while not announceVal:
|
while not announceVal:
|
||||||
announceAttemptCount += 1
|
announceAttemptCount += 1
|
||||||
announceVal = self.performGet('announce', command[1], data=self._core.hsAdder.replace('\n', ''), skipHighFailureAddress=True)
|
announceVal = self.performGet('announce', command[1], data=self._core.hsAdder.replace('\n', ''), skipHighFailureAddress=True)
|
||||||
logger.info(announceVal)
|
# logger.info(announceVal)
|
||||||
if announceAttemptCount >= announceAttempts:
|
if announceAttemptCount >= announceAttempts:
|
||||||
logger.warn('Unable to announce to ' + command[1])
|
logger.warn('Unable to announce to %s' % command[1])
|
||||||
break
|
break
|
||||||
elif command[0] == 'runCheck':
|
elif command[0] == 'runCheck':
|
||||||
logger.info('Status check; looks good.')
|
logger.debug('Status check; looks good.')
|
||||||
open('data/.runcheck', 'w+').close()
|
open('data/.runcheck', 'w+').close()
|
||||||
elif command[0] == 'kex':
|
elif command[0] == 'kex':
|
||||||
self.pexCount = pexTimer - 1
|
self.pexCount = pexTimer - 1
|
||||||
|
@ -188,13 +188,17 @@ class OnionrCommunicate:
|
||||||
id_peer_cache = {}
|
id_peer_cache = {}
|
||||||
|
|
||||||
def registerTimer(self, timerName, rate, timerFunc=None):
|
def registerTimer(self, timerName, rate, timerFunc=None):
|
||||||
'''Register a communicator timer'''
|
'''
|
||||||
|
Register a communicator timer
|
||||||
|
'''
|
||||||
self.communicatorTimers[timerName] = rate
|
self.communicatorTimers[timerName] = rate
|
||||||
self.communicatorTimerCounts[timerName] = 0
|
self.communicatorTimerCounts[timerName] = 0
|
||||||
self.communicatorTimerFuncs[timerName] = timerFunc
|
self.communicatorTimerFuncs[timerName] = timerFunc
|
||||||
|
|
||||||
def timerTick(self):
|
def timerTick(self):
|
||||||
'''Increments timers "ticks" and calls funcs if applicable'''
|
'''
|
||||||
|
Increments timers "ticks" and calls funcs if applicable
|
||||||
|
'''
|
||||||
tName = ''
|
tName = ''
|
||||||
for i in self.communicatorTimers.items():
|
for i in self.communicatorTimers.items():
|
||||||
tName = i[0]
|
tName = i[0]
|
||||||
|
@ -617,7 +621,9 @@ class OnionrCommunicate:
|
||||||
return
|
return
|
||||||
|
|
||||||
def removeBlockFromProcessingList(self, block):
|
def removeBlockFromProcessingList(self, block):
|
||||||
'''Remove a block from the processing list'''
|
'''
|
||||||
|
Remove a block from the processing list
|
||||||
|
'''
|
||||||
try:
|
try:
|
||||||
self.blocksProcessing.remove(block)
|
self.blocksProcessing.remove(block)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -724,7 +730,8 @@ class OnionrCommunicate:
|
||||||
r = requests.get(url, headers=headers, proxies=proxies, allow_redirects=False, timeout=(15, 30))
|
r = requests.get(url, headers=headers, proxies=proxies, allow_redirects=False, timeout=(15, 30))
|
||||||
retData = r.text
|
retData = r.text
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
logger.debug("%s failed with peer %s" % (action, peer))
|
logger.debug('%s failed with peer %s' % (action, peer))
|
||||||
|
logger.debug('Error: %s' % str(e))
|
||||||
retData = False
|
retData = False
|
||||||
|
|
||||||
if not retData:
|
if not retData:
|
||||||
|
|
|
@ -103,7 +103,7 @@ DataDirectory data/tordata/
|
||||||
logger.fatal("Got keyboard interrupt")
|
logger.fatal("Got keyboard interrupt")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
logger.info('Finished starting Tor', timestamp=True)
|
logger.debug('Finished starting Tor.', timestamp=True)
|
||||||
self.readyState = True
|
self.readyState = True
|
||||||
|
|
||||||
myID = open('data/hs/hostname', 'r')
|
myID = open('data/hs/hostname', 'r')
|
||||||
|
|
|
@ -31,6 +31,7 @@ import api, core, config, logger, onionrplugins as plugins, onionrevents as even
|
||||||
import onionrutils
|
import onionrutils
|
||||||
from onionrutils import OnionrUtils
|
from onionrutils import OnionrUtils
|
||||||
from netcontroller import NetController
|
from netcontroller import NetController
|
||||||
|
from onionrblockapi import Block
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from urllib3.contrib.socks import SOCKSProxyManager
|
from urllib3.contrib.socks import SOCKSProxyManager
|
||||||
|
@ -192,8 +193,11 @@ class Onionr:
|
||||||
'add-addr': self.addAddress,
|
'add-addr': self.addAddress,
|
||||||
'addaddr': self.addAddress,
|
'addaddr': self.addAddress,
|
||||||
'addaddress': self.addAddress,
|
'addaddress': self.addAddress,
|
||||||
|
|
||||||
|
'add-file': self.addFile,
|
||||||
'addfile': self.addFile,
|
'addfile': self.addFile,
|
||||||
|
|
||||||
|
'import-blocks': self.onionrUtils.importNewBlocks,
|
||||||
'importblocks': self.onionrUtils.importNewBlocks,
|
'importblocks': self.onionrUtils.importNewBlocks,
|
||||||
|
|
||||||
'introduce': self.onionrCore.introduceNode,
|
'introduce': self.onionrCore.introduceNode,
|
||||||
|
@ -216,8 +220,8 @@ class Onionr:
|
||||||
'add-msg': 'Broadcasts a message to the Onionr network',
|
'add-msg': 'Broadcasts a message to the Onionr network',
|
||||||
'pm': 'Adds a private message to block',
|
'pm': 'Adds a private message to block',
|
||||||
'get-pms': 'Shows private messages sent to you',
|
'get-pms': 'Shows private messages sent to you',
|
||||||
'addfile': 'Create an Onionr block from a file',
|
'add-file': 'Create an Onionr block from a file',
|
||||||
'importblocks': 'import blocks from the disk (Onionr is transport-agnostic!)',
|
'import-blocks': 'import blocks from the disk (Onionr is transport-agnostic!)',
|
||||||
'introduce': 'Introduce your node to the public Onionr network',
|
'introduce': 'Introduce your node to the public Onionr network',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,12 +395,11 @@ class Onionr:
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
return
|
return
|
||||||
|
|
||||||
#addedHash = self.onionrCore.setData(messageToAdd)
|
addedHash = Block('txt', messageToAdd).save()
|
||||||
addedHash = self.onionrCore.insertBlock(messageToAdd, header='txt')
|
if addedHash != None:
|
||||||
#self.onionrCore.addToBlockDB(addedHash, selfInsert=True)
|
|
||||||
#self.onionrCore.setBlockType(addedHash, 'txt')
|
|
||||||
if addedHash != '':
|
|
||||||
logger.info("Message inserted as as block %s" % addedHash)
|
logger.info("Message inserted as as block %s" % addedHash)
|
||||||
|
else:
|
||||||
|
logger.error('Failed to insert block.', timestamp = False)
|
||||||
return
|
return
|
||||||
|
|
||||||
def getPMs(self):
|
def getPMs(self):
|
||||||
|
@ -520,12 +523,12 @@ class Onionr:
|
||||||
|
|
||||||
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!)', timestamp = False)
|
||||||
net = NetController(config.get('client')['port'])
|
net = NetController(config.get('client')['port'])
|
||||||
logger.info('Tor is starting...')
|
logger.info('Tor is starting...')
|
||||||
if not net.startTor():
|
if not net.startTor():
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
logger.info('Started Tor .onion service: ' + logger.colors.underline + net.myID)
|
logger.info('Started .onion service: ' + logger.colors.underline + net.myID)
|
||||||
logger.info('Our Public key: ' + self.onionrCore._crypto.pubKey)
|
logger.info('Our Public key: ' + self.onionrCore._crypto.pubKey)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
subprocess.Popen(["./communicator.py", "run", str(net.socksPort)])
|
subprocess.Popen(["./communicator.py", "run", str(net.socksPort)])
|
||||||
|
@ -562,6 +565,9 @@ class Onionr:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# define stats messages here
|
# define stats messages here
|
||||||
|
totalBlocks = len(Block.getBlocks())
|
||||||
|
signedBlocks = len(Block.getBlocks(signed = True))
|
||||||
|
|
||||||
messages = {
|
messages = {
|
||||||
# info about local client
|
# info about local client
|
||||||
'Onionr Daemon Status' : ((logger.colors.fg.green + 'Online') if self.onionrUtils.isCommunicatorRunning(timeout = 2) else logger.colors.fg.red + 'Offline'),
|
'Onionr Daemon Status' : ((logger.colors.fg.green + 'Online') if self.onionrUtils.isCommunicatorRunning(timeout = 2) else logger.colors.fg.red + 'Offline'),
|
||||||
|
@ -577,7 +583,9 @@ class Onionr:
|
||||||
# count stats
|
# count stats
|
||||||
'div2' : True,
|
'div2' : True,
|
||||||
'Known Peers Count' : str(len(self.onionrCore.listPeers()) - 1),
|
'Known Peers Count' : str(len(self.onionrCore.listPeers()) - 1),
|
||||||
'Enabled Plugins Count' : str(len(config.get('plugins')['enabled'])) + ' / ' + str(len(os.listdir('data/plugins/')))
|
'Enabled Plugins Count' : str(len(config.get('plugins')['enabled'])) + ' / ' + str(len(os.listdir('data/plugins/'))),
|
||||||
|
'Known Blocks Count' : str(totalBlocks),
|
||||||
|
'Percent Blocks Signed' : str(round(100 * signedBlocks / totalBlocks, 2)) + '%'
|
||||||
}
|
}
|
||||||
|
|
||||||
# color configuration
|
# color configuration
|
||||||
|
@ -639,18 +647,30 @@ class Onionr:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def addFile(self):
|
def addFile(self):
|
||||||
'''command to add a file to the onionr network'''
|
'''
|
||||||
if len(sys.argv) >= 2:
|
Adds a file to the onionr network
|
||||||
newFile = sys.argv[2]
|
'''
|
||||||
logger.info('Attempting to add file...')
|
|
||||||
try:
|
if len(sys.argv) >= 3:
|
||||||
with open(newFile, 'rb') as new:
|
filename = sys.argv[2]
|
||||||
new = new.read()
|
contents = None
|
||||||
except FileNotFoundError:
|
|
||||||
|
if not os.path.exists(filename):
|
||||||
logger.warn('That file does not exist. Improper path?')
|
logger.warn('That file does not exist. Improper path?')
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(filename, 'rb') as file:
|
||||||
|
contents = file.read().decode()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not contents is None:
|
||||||
|
blockhash = Block('bin', contents).save()
|
||||||
|
logger.info('File %s saved in block %s.' % (filename, blockhash))
|
||||||
else:
|
else:
|
||||||
logger.debug(new)
|
logger.error('Failed to save file in block.', timestamp = False)
|
||||||
logger.info(self.onionrCore.insertBlock(new, header='bin'))
|
else:
|
||||||
|
logger.error('%s add-file <filename>' % sys.argv[0], timestamp = False)
|
||||||
|
|
||||||
|
|
||||||
Onionr()
|
Onionr()
|
||||||
|
|
|
@ -77,7 +77,7 @@ def enable(name, onionr = None, start_event = True):
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
logger.error('Failed to enable plugin \"' + name + '\", disabling plugin.')
|
logger.error('Failed to enable plugin \"%s\", disabling plugin.' % name)
|
||||||
disable(name)
|
disable(name)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -121,9 +121,9 @@ def start(name, onionr = None):
|
||||||
|
|
||||||
return plugin
|
return plugin
|
||||||
except:
|
except:
|
||||||
logger.error('Failed to start module \"' + name + '\".')
|
logger.error('Failed to start module \"%s\".' % name)
|
||||||
else:
|
else:
|
||||||
logger.error('Failed to start nonexistant module \"' + name + '\".')
|
logger.error('Failed to start nonexistant module \"%s\".' % name)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -145,9 +145,9 @@ def stop(name, onionr = None):
|
||||||
|
|
||||||
return plugin
|
return plugin
|
||||||
except:
|
except:
|
||||||
logger.error('Failed to stop module \"' + name + '\".')
|
logger.error('Failed to stop module \"%s\".' % name)
|
||||||
else:
|
else:
|
||||||
logger.error('Failed to stop nonexistant module \"' + name + '\".')
|
logger.error('Failed to stop nonexistant module \"%s\".' % name)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import nacl.encoding, nacl.hash, nacl.utils, time, math, threading, binascii, lo
|
||||||
import core
|
import core
|
||||||
|
|
||||||
class POW:
|
class POW:
|
||||||
def pow(self, reporting = False):
|
def pow(self, reporting = False, myCore = None):
|
||||||
startTime = math.floor(time.time())
|
startTime = math.floor(time.time())
|
||||||
self.hashing = True
|
self.hashing = True
|
||||||
self.reporting = reporting
|
self.reporting = reporting
|
||||||
|
@ -30,7 +30,7 @@ class POW:
|
||||||
answer = ''
|
answer = ''
|
||||||
heartbeat = 200000
|
heartbeat = 200000
|
||||||
hbCount = 0
|
hbCount = 0
|
||||||
myCore = core.Core()
|
|
||||||
while self.hashing:
|
while self.hashing:
|
||||||
rand = nacl.utils.random()
|
rand = nacl.utils.random()
|
||||||
token = nacl.hash.blake2b(rand + self.data).decode()
|
token = nacl.hash.blake2b(rand + self.data).decode()
|
||||||
|
@ -39,23 +39,22 @@ class POW:
|
||||||
self.hashing = False
|
self.hashing = False
|
||||||
iFound = True
|
iFound = True
|
||||||
break
|
break
|
||||||
else:
|
|
||||||
logger.debug('POW thread exiting, another thread found result')
|
|
||||||
if iFound:
|
if iFound:
|
||||||
endTime = math.floor(time.time())
|
endTime = math.floor(time.time())
|
||||||
if self.reporting:
|
if self.reporting:
|
||||||
logger.info('Found token ' + token, timestamp=True)
|
logger.debug('Found token after %s seconds: %s' % (endTime - startTime, token), timestamp=True)
|
||||||
logger.info('rand value: ' + base64.b64encode(rand).decode())
|
logger.debug('Random value was: %s' % base64.b64encode(rand).decode())
|
||||||
logger.info('took ' + str(endTime - startTime) + ' seconds', timestamp=True)
|
|
||||||
self.result = (token, rand)
|
self.result = (token, rand)
|
||||||
|
|
||||||
def __init__(self, data):
|
def __init__(self, data, threadCount = 5):
|
||||||
self.foundHash = False
|
self.foundHash = False
|
||||||
self.difficulty = 0
|
self.difficulty = 0
|
||||||
self.data = data
|
self.data = data
|
||||||
|
self.threadCount = threadCount
|
||||||
|
|
||||||
dataLen = sys.getsizeof(data)
|
dataLen = sys.getsizeof(data)
|
||||||
self.difficulty = math.floor(dataLen/1000000)
|
self.difficulty = math.floor(dataLen / 1000000)
|
||||||
if self.difficulty <= 2:
|
if self.difficulty <= 2:
|
||||||
self.difficulty = 4
|
self.difficulty = 4
|
||||||
|
|
||||||
|
@ -63,19 +62,19 @@ class POW:
|
||||||
self.data = self.data.encode()
|
self.data = self.data.encode()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self.data = nacl.hash.blake2b(self.data)
|
self.data = nacl.hash.blake2b(self.data)
|
||||||
|
|
||||||
logger.debug('Computing difficulty of ' + str(self.difficulty))
|
logger.info('Computing POW (difficulty: %s)...' % self.difficulty)
|
||||||
|
|
||||||
|
self.mainHash = '0' * 70
|
||||||
|
self.puzzle = self.mainHash[0:min(self.difficulty, len(self.mainHash))]
|
||||||
|
|
||||||
|
myCore = core.Core()
|
||||||
|
for i in range(max(1, threadCount)):
|
||||||
|
t = threading.Thread(name = 'thread%s' % i, target = self.pow, args = (True,myCore))
|
||||||
|
t.start()
|
||||||
|
|
||||||
self.mainHash = '0000000000000000000000000000000000000000000000000000000000000000'#nacl.hash.blake2b(nacl.utils.random()).decode()
|
|
||||||
self.puzzle = self.mainHash[0:self.difficulty]
|
|
||||||
#logger.debug('trying to find ' + str(self.mainHash))
|
|
||||||
tOne = threading.Thread(name='one', target=self.pow, args=(True,))
|
|
||||||
tTwo = threading.Thread(name='two', target=self.pow, args=(True,))
|
|
||||||
tThree = threading.Thread(name='three', target=self.pow, args=(True,))
|
|
||||||
tOne.start()
|
|
||||||
tTwo.start()
|
|
||||||
tThree.start()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
|
@ -89,9 +88,11 @@ class POW:
|
||||||
'''
|
'''
|
||||||
Returns the result then sets to false, useful to automatically clear the result
|
Returns the result then sets to false, useful to automatically clear the result
|
||||||
'''
|
'''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
retVal = self.result
|
retVal = self.result
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
retVal = False
|
retVal = False
|
||||||
|
|
||||||
self.result = False
|
self.result = False
|
||||||
return retVal
|
return retVal
|
||||||
|
|
|
@ -34,9 +34,9 @@ def writeKeys():
|
||||||
Serializes and writes the keystore in memory to file
|
Serializes and writes the keystore in memory to file
|
||||||
'''
|
'''
|
||||||
|
|
||||||
file = open(keys_file, 'w')
|
with open(keys_file, 'w') as file:
|
||||||
file.write(json.dumps(keys_data, indent=4, sort_keys=True))
|
file.write(json.dumps(keys_data, indent=4, sort_keys=True))
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
def readKeys():
|
def readKeys():
|
||||||
'''
|
'''
|
||||||
|
@ -44,7 +44,8 @@ def readKeys():
|
||||||
'''
|
'''
|
||||||
|
|
||||||
global keys_data
|
global keys_data
|
||||||
keys_data = json.loads(open(keys_file).read())
|
with open(keys_file) as file:
|
||||||
|
keys_data = json.loads(file.read())
|
||||||
return keys_data
|
return keys_data
|
||||||
|
|
||||||
def getKey(plugin):
|
def getKey(plugin):
|
||||||
|
@ -106,27 +107,37 @@ def getRepositories():
|
||||||
readKeys()
|
readKeys()
|
||||||
return keys_data['repositories']
|
return keys_data['repositories']
|
||||||
|
|
||||||
def addRepository(repositories, data):
|
def addRepository(blockhash, data):
|
||||||
'''
|
'''
|
||||||
Saves the plugin name, to remember that it was installed by the pluginmanager
|
Saves the plugin name, to remember that it was installed by the pluginmanager
|
||||||
'''
|
'''
|
||||||
|
|
||||||
global keys_data
|
global keys_data
|
||||||
readKeys()
|
readKeys()
|
||||||
keys_data['repositories'][repositories] = data
|
keys_data['repositories'][blockhash] = data
|
||||||
writeKeys()
|
writeKeys()
|
||||||
|
|
||||||
def removeRepository(repositories):
|
def removeRepository(blockhash):
|
||||||
'''
|
'''
|
||||||
Removes the plugin name from the pluginmanager's records
|
Removes the plugin name from the pluginmanager's records
|
||||||
'''
|
'''
|
||||||
|
|
||||||
global keys_data
|
global keys_data
|
||||||
readKeys()
|
readKeys()
|
||||||
if plugin in keys_data['repositories']:
|
if blockhash in keys_data['repositories']:
|
||||||
del keys_data['repositories'][repositories]
|
del keys_data['repositories'][blockhash]
|
||||||
writeKeys()
|
writeKeys()
|
||||||
|
|
||||||
|
def createRepository(plugins):
|
||||||
|
contents = {'plugins' : plugins, 'author' : getpass.getuser(), 'compiled-by' : plugin_name}
|
||||||
|
|
||||||
|
block = Block(core = pluginapi.get_core())
|
||||||
|
|
||||||
|
block.setType('repository')
|
||||||
|
block.setContent(json.dumps(contents))
|
||||||
|
|
||||||
|
return block.save(True)
|
||||||
|
|
||||||
def check():
|
def check():
|
||||||
'''
|
'''
|
||||||
Checks to make sure the keystore file still exists
|
Checks to make sure the keystore file still exists
|
||||||
|
@ -144,7 +155,7 @@ def sanitize(name):
|
||||||
|
|
||||||
def blockToPlugin(block):
|
def blockToPlugin(block):
|
||||||
try:
|
try:
|
||||||
block = Block(block)
|
block = Block(block, core = pluginapi.get_core())
|
||||||
blockContent = json.loads(block.getContent())
|
blockContent = json.loads(block.getContent())
|
||||||
|
|
||||||
name = sanitize(blockContent['name'])
|
name = sanitize(blockContent['name'])
|
||||||
|
@ -194,14 +205,19 @@ def pluginToBlock(plugin, import_block = True):
|
||||||
shutil.rmtree(directory + '__pycache__')
|
shutil.rmtree(directory + '__pycache__')
|
||||||
|
|
||||||
shutil.make_archive(zipfile[:-4], 'zip', directory)
|
shutil.make_archive(zipfile[:-4], 'zip', directory)
|
||||||
data = base64.b64encode(open(zipfile, 'rb').read())
|
data = ''
|
||||||
|
with open(zipfile, 'rb') as file:
|
||||||
|
data = base64.b64encode(file.read())
|
||||||
|
|
||||||
author = getpass.getuser()
|
author = getpass.getuser()
|
||||||
description = 'Default plugin description'
|
description = 'Default plugin description'
|
||||||
info = {"name" : plugin}
|
info = {"name" : plugin}
|
||||||
try:
|
try:
|
||||||
if os.path.exists(directory + 'info.json'):
|
if os.path.exists(directory + 'info.json'):
|
||||||
info = json.loads(open(directory + 'info.json').read())
|
info = ''
|
||||||
|
with open(directory + 'info.json').read() as file:
|
||||||
|
info = json.loads(file.read())
|
||||||
|
|
||||||
if 'author' in info:
|
if 'author' in info:
|
||||||
author = info['author']
|
author = info['author']
|
||||||
if 'description' in info:
|
if 'description' in info:
|
||||||
|
@ -211,7 +227,13 @@ def pluginToBlock(plugin, import_block = True):
|
||||||
|
|
||||||
metadata = {'author' : author, 'date' : str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')), 'name' : plugin, 'info' : info, 'compiled-by' : plugin_name, 'content' : data.decode('utf-8'), 'description' : description}
|
metadata = {'author' : author, 'date' : str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')), 'name' : plugin, 'info' : info, 'compiled-by' : plugin_name, 'content' : data.decode('utf-8'), 'description' : description}
|
||||||
|
|
||||||
hash = pluginapi.get_core().insertBlock(json.dumps(metadata), header = 'plugin', sign = True)
|
block = Block(core = pluginapi.get_core())
|
||||||
|
|
||||||
|
block.setType('plugin')
|
||||||
|
block.setContent(json.dumps(metadata))
|
||||||
|
|
||||||
|
hash = block.save(True)
|
||||||
|
# hash = pluginapi.get_core().insertBlock(, header = 'plugin', sign = True)
|
||||||
|
|
||||||
if import_block:
|
if import_block:
|
||||||
pluginapi.get_utils().importNewBlocks()
|
pluginapi.get_utils().importNewBlocks()
|
||||||
|
@ -226,7 +248,7 @@ def pluginToBlock(plugin, import_block = True):
|
||||||
|
|
||||||
def installBlock(block):
|
def installBlock(block):
|
||||||
try:
|
try:
|
||||||
block = Block(block)
|
block = Block(block, core = pluginapi.get_core())
|
||||||
blockContent = json.loads(block.getContent())
|
blockContent = json.loads(block.getContent())
|
||||||
|
|
||||||
name = sanitize(blockContent['name'])
|
name = sanitize(blockContent['name'])
|
||||||
|
@ -353,7 +375,8 @@ def commandInstallPlugin():
|
||||||
choice = logger.readline('Select the number of the key to use, from 1 to %s, or press Ctrl+C to cancel:' % (index - 1))
|
choice = logger.readline('Select the number of the key to use, from 1 to %s, or press Ctrl+C to cancel:' % (index - 1))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if int(choice) < index and int(choice) >= 1:
|
choice = int(choice)
|
||||||
|
if choice <= index and choice >= 1:
|
||||||
distributor = distributors[int(choice)]
|
distributor = distributors[int(choice)]
|
||||||
valid = True
|
valid = True
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
@ -368,9 +391,11 @@ def commandInstallPlugin():
|
||||||
logger.warn('Failed to lookup plugin in repositories.', timestamp = False)
|
logger.warn('Failed to lookup plugin in repositories.', timestamp = False)
|
||||||
logger.error('asdf', error = e, timestamp = False)
|
logger.error('asdf', error = e, timestamp = False)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
if pkobh is None:
|
if pkobh is None:
|
||||||
logger.error('No key for this plugin found in keystore or repositories, please specify.')
|
logger.error('No key for this plugin found in keystore or repositories, please specify.', timestamp = False)
|
||||||
help()
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
valid_hash = pluginapi.get_utils().validateHash(pkobh)
|
valid_hash = pluginapi.get_utils().validateHash(pkobh)
|
||||||
|
@ -386,7 +411,7 @@ def commandInstallPlugin():
|
||||||
blockhash = None
|
blockhash = None
|
||||||
|
|
||||||
if valid_hash and not real_block:
|
if valid_hash and not real_block:
|
||||||
logger.error('Block hash not found. Perhaps it has not been synced yet?')
|
logger.error('Block hash not found. Perhaps it has not been synced yet?', timestamp = False)
|
||||||
logger.debug('Is valid hash, but does not belong to a known block.')
|
logger.debug('Is valid hash, but does not belong to a known block.')
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -396,7 +421,7 @@ def commandInstallPlugin():
|
||||||
|
|
||||||
installBlock(blockhash)
|
installBlock(blockhash)
|
||||||
elif valid_key and not real_key:
|
elif valid_key and not real_key:
|
||||||
logger.error('Public key not found. Try adding the node by address manually, if possible.')
|
logger.error('Public key not found. Try adding the node by address manually, if possible.', timestamp = False)
|
||||||
logger.debug('Is valid key, but the key is not a known one.')
|
logger.debug('Is valid key, but the key is not a known one.')
|
||||||
elif valid_key and real_key:
|
elif valid_key and real_key:
|
||||||
publickey = str(pkobh)
|
publickey = str(pkobh)
|
||||||
|
@ -432,10 +457,11 @@ def commandInstallPlugin():
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
logger.warn('Only continue the installation is you are absolutely certain that you trust the plugin distributor. Public key of plugin distributor: %s' % publickey, timestamp = False)
|
logger.warn('Only continue the installation if you are absolutely certain that you trust the plugin distributor. Public key of plugin distributor: %s' % publickey, timestamp = False)
|
||||||
|
logger.debug('Most recent block matching parameters is %s' % mostRecentVersionBlock)
|
||||||
installBlock(mostRecentVersionBlock)
|
installBlock(mostRecentVersionBlock)
|
||||||
else:
|
else:
|
||||||
logger.error('Unknown data "%s"; must be public key or block hash.' % str(pkobh))
|
logger.error('Unknown data "%s"; must be public key or block hash.' % str(pkobh), timestamp = False)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin> [public key/block hash]')
|
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin> [public key/block hash]')
|
||||||
|
@ -463,11 +489,11 @@ def commandAddRepository():
|
||||||
if pluginapi.get_utils().validateHash(blockhash):
|
if pluginapi.get_utils().validateHash(blockhash):
|
||||||
if Block.exists(blockhash):
|
if Block.exists(blockhash):
|
||||||
try:
|
try:
|
||||||
blockContent = json.loads(Block(blockhash).getContent())
|
blockContent = json.loads(Block(blockhash, core = pluginapi.get_core()).getContent())
|
||||||
|
|
||||||
pluginslist = dict()
|
pluginslist = dict()
|
||||||
|
|
||||||
for pluginname, distributor in blockContent['plugins'].items():
|
for pluginname, distributor in blockContent['plugins']:
|
||||||
if pluginapi.get_utils().validatePubKey(distributor):
|
if pluginapi.get_utils().validatePubKey(distributor):
|
||||||
pluginslist[pluginname] = distributor
|
pluginslist[pluginname] = distributor
|
||||||
|
|
||||||
|
@ -477,14 +503,14 @@ def commandAddRepository():
|
||||||
addRepository(blockhash, pluginslist)
|
addRepository(blockhash, pluginslist)
|
||||||
logger.info('Successfully added repository.')
|
logger.info('Successfully added repository.')
|
||||||
else:
|
else:
|
||||||
logger.error('Repository contains no records, not importing.')
|
logger.error('Repository contains no records, not importing.', timestamp = False)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Failed to parse block.', error = e)
|
logger.error('Failed to parse block.', error = e)
|
||||||
else:
|
else:
|
||||||
logger.error('Block hash not found. Perhaps it has not been synced yet?')
|
logger.error('Block hash not found. Perhaps it has not been synced yet?', timestamp = False)
|
||||||
logger.debug('Is valid hash, but does not belong to a known block.')
|
logger.debug('Is valid hash, but does not belong to a known block.')
|
||||||
else:
|
else:
|
||||||
logger.error('Unknown data "%s"; must be block hash.' % str(pkobh))
|
logger.error('Unknown data "%s"; must be block hash.' % str(pkobh), timestamp = False)
|
||||||
else:
|
else:
|
||||||
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' [block hash]')
|
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' [block hash]')
|
||||||
|
|
||||||
|
@ -500,10 +526,11 @@ def commandRemoveRepository():
|
||||||
if blockhash in getRepositories():
|
if blockhash in getRepositories():
|
||||||
try:
|
try:
|
||||||
removeRepository(blockhash)
|
removeRepository(blockhash)
|
||||||
|
logger.info('Successfully removed repository.')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Failed to parse block.', error = e)
|
logger.error('Failed to parse block.', error = e)
|
||||||
else:
|
else:
|
||||||
logger.error('Repository has not been imported, nothing to remove.')
|
logger.error('Repository has not been imported, nothing to remove.', timestamp = False)
|
||||||
else:
|
else:
|
||||||
logger.error('Unknown data "%s"; must be block hash.' % str(pkobh))
|
logger.error('Unknown data "%s"; must be block hash.' % str(pkobh))
|
||||||
else:
|
else:
|
||||||
|
@ -526,6 +553,48 @@ def commandPublishPlugin():
|
||||||
else:
|
else:
|
||||||
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin>')
|
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin>')
|
||||||
|
|
||||||
|
def commandCreateRepository():
|
||||||
|
if len(sys.argv) >= 3:
|
||||||
|
check()
|
||||||
|
|
||||||
|
plugins = list()
|
||||||
|
script = sys.argv[0]
|
||||||
|
|
||||||
|
del sys.argv[:2]
|
||||||
|
success = True
|
||||||
|
for pluginname in sys.argv:
|
||||||
|
distributor = None
|
||||||
|
|
||||||
|
if ':' in pluginname:
|
||||||
|
split = pluginname.split(':')
|
||||||
|
pluginname = split[0]
|
||||||
|
distributor = split[1]
|
||||||
|
|
||||||
|
pluginname = sanitize(pluginname)
|
||||||
|
|
||||||
|
if distributor is None:
|
||||||
|
distributor = getKey(pluginname)
|
||||||
|
if distributor is None:
|
||||||
|
logger.error('No distributor key was found for the plugin %s.' % pluginname, timestamp = False)
|
||||||
|
success = False
|
||||||
|
|
||||||
|
plugins.append([pluginname, distributor])
|
||||||
|
|
||||||
|
if not success:
|
||||||
|
logger.error('Please correct the above errors, then recreate the repository.')
|
||||||
|
return True
|
||||||
|
|
||||||
|
blockhash = createRepository(plugins)
|
||||||
|
print(blockhash)
|
||||||
|
if not blockhash is None:
|
||||||
|
logger.info('Successfully created repository. Execute the following command to add the repository:\n ' + logger.colors.underline + '%s --add-repository %s' % (script, blockhash))
|
||||||
|
else:
|
||||||
|
logger.error('Failed to create repository, an unknown error occurred.')
|
||||||
|
else:
|
||||||
|
logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' [plugins...]')
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
# event listeners
|
# event listeners
|
||||||
|
|
||||||
def on_init(api, data = None):
|
def on_init(api, data = None):
|
||||||
|
@ -540,6 +609,7 @@ def on_init(api, data = None):
|
||||||
api.commands.register(['add-repo', 'add-repository', 'addrepo', 'addrepository', 'repository-add', 'repo-add', 'repoadd', 'addrepository', 'add-plugin-repository', 'add-plugin-repo', 'add-pluginrepo', 'add-pluginrepository', 'addpluginrepo', 'addpluginrepository'], commandAddRepository)
|
api.commands.register(['add-repo', 'add-repository', 'addrepo', 'addrepository', 'repository-add', 'repo-add', 'repoadd', 'addrepository', 'add-plugin-repository', 'add-plugin-repo', 'add-pluginrepo', 'add-pluginrepository', 'addpluginrepo', 'addpluginrepository'], commandAddRepository)
|
||||||
api.commands.register(['remove-repo', 'remove-repository', 'removerepo', 'removerepository', 'repository-remove', 'repo-remove', 'reporemove', 'removerepository', 'remove-plugin-repository', 'remove-plugin-repo', 'remove-pluginrepo', 'remove-pluginrepository', 'removepluginrepo', 'removepluginrepository', 'rm-repo', 'rm-repository', 'rmrepo', 'rmrepository', 'repository-rm', 'repo-rm', 'reporm', 'rmrepository', 'rm-plugin-repository', 'rm-plugin-repo', 'rm-pluginrepo', 'rm-pluginrepository', 'rmpluginrepo', 'rmpluginrepository'], commandRemoveRepository)
|
api.commands.register(['remove-repo', 'remove-repository', 'removerepo', 'removerepository', 'repository-remove', 'repo-remove', 'reporemove', 'removerepository', 'remove-plugin-repository', 'remove-plugin-repo', 'remove-pluginrepo', 'remove-pluginrepository', 'removepluginrepo', 'removepluginrepository', 'rm-repo', 'rm-repository', 'rmrepo', 'rmrepository', 'repository-rm', 'repo-rm', 'reporm', 'rmrepository', 'rm-plugin-repository', 'rm-plugin-repo', 'rm-pluginrepo', 'rm-pluginrepository', 'rmpluginrepo', 'rmpluginrepository'], commandRemoveRepository)
|
||||||
api.commands.register(['publish-plugin', 'plugin-publish', 'publishplugin', 'pluginpublish', 'publish'], commandPublishPlugin)
|
api.commands.register(['publish-plugin', 'plugin-publish', 'publishplugin', 'pluginpublish', 'publish'], commandPublishPlugin)
|
||||||
|
api.commands.register(['create-repository', 'create-repo', 'createrepo', 'createrepository', 'repocreate'], commandCreateRepository)
|
||||||
|
|
||||||
# add help menus once the features are actually implemented
|
# add help menus once the features are actually implemented
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue