diff --git a/src/bitmessagecli.py b/src/bitmessagecli.py index 00eca944..69d24841 100644 --- a/src/bitmessagecli.py +++ b/src/bitmessagecli.py @@ -1,15 +1,20 @@ -#!/usr/bin/python2.7 +#!/usr/bin/python2.7 # -*- coding: utf-8 -*- -# Created by Adam Melton (.dok) referenceing https://bitmessage.org/wiki/API_Reference for API documentation -# Distributed under the MIT/X11 software license. See http://www.opensource.org/licenses/mit-license.php. +# pylint: disable=too-many-lines,global-statement,too-many-branches,too-many-statements,inconsistent-return-statements +# pylint: disable=too-many-nested-blocks,too-many-locals,protected-access,too-many-arguments,too-many-function-args +# pylint: disable=no-member +""" +Created by Adam Melton (.dok) referenceing https://bitmessage.org/wiki/API_Reference for API documentation +Distributed under the MIT/X11 software license. See http://www.opensource.org/licenses/mit-license.php. -# This is an example of a daemon client for PyBitmessage 0.6.2, by .dok (Version 0.3.1) , modified +This is an example of a daemon client for PyBitmessage 0.6.2, by .dok (Version 0.3.1) , modified +TODO: fix the following (currently ignored) violations: + +""" import xmlrpclib import datetime -#import hashlib -#import getopt import imghdr import ntpath import json @@ -20,79 +25,99 @@ import os from bmconfigparser import BMConfigParser + api = '' keysName = 'keys.dat' keysPath = 'keys.dat' -usrPrompt = 0 #0 = First Start, 1 = prompt, 2 = no prompt if the program is starting up +usrPrompt = 0 # 0 = First Start, 1 = prompt, 2 = no prompt if the program is starting up knownAddresses = dict() -def userInput(message): #Checks input for exit or quit. Also formats for input, etc + +def userInput(message): + """Checks input for exit or quit. Also formats for input, etc""" + global usrPrompt + print '\n' + message uInput = raw_input('> ') - if (uInput.lower() == 'exit'): #Returns the user to the main menu + if uInput.lower() == 'exit': # Returns the user to the main menu usrPrompt = 1 main() - - elif (uInput.lower() == 'quit'): #Quits the program + + elif uInput.lower() == 'quit': # Quits the program print '\n Bye\n' - sys.exit() - os._exit() # _ + sys.exit(0) + else: return uInput - -def restartBmNotify(): #Prompts the user to restart Bitmessage. + + +def restartBmNotify(): + """Prompt the user to restart Bitmessage""" print '\n *******************************************************************' print ' WARNING: If Bitmessage is running locally, you must restart it now.' print ' *******************************************************************\n' -#Begin keys.dat interactions -def lookupAppdataFolder(): #gets the appropriate folders for the .dat files depending on the OS. Taken from bitmessagemain.py + +# Begin keys.dat interactions + + +def lookupAppdataFolder(): + """gets the appropriate folders for the .dat files depending on the OS. Taken from bitmessagemain.py""" + APPNAME = "PyBitmessage" - from os import path, environ if sys.platform == 'darwin': - if "HOME" in environ: - dataFolder = path.join(os.environ["HOME"], "Library/Application support/", APPNAME) + '/' + if "HOME" in os.environ: + dataFolder = os.path.join(os.environ["HOME"], "Library/Application support/", APPNAME) + '/' else: - print ' Could not find home folder, please report this message and your OS X version to the Daemon Github.' - os._exit() + print( + ' Could not find home folder, please report ' + 'this message and your OS X version to the Daemon Github.') + sys.exit(1) elif 'win32' in sys.platform or 'win64' in sys.platform: - dataFolder = path.join(environ['APPDATA'], APPNAME) + '\\' + dataFolder = os.path.join(os.environ['APPDATA'], APPNAME) + '\\' else: - dataFolder = path.expanduser(path.join("~", ".config/" + APPNAME + "/")) + dataFolder = os.path.expanduser(os.path.join("~", ".config/" + APPNAME + "/")) return dataFolder + def configInit(): + """Initialised the configuration""" + BMConfigParser().add_section('bitmessagesettings') - BMConfigParser().set('bitmessagesettings', 'port', '8444') #Sets the bitmessage port to stop the warning about the api not properly being setup. This is in the event that the keys.dat is in a different directory or is created locally to connect to a machine remotely. - BMConfigParser().set('bitmessagesettings','apienabled','true') #Sets apienabled to true in keys.dat - + # Sets the bitmessage port to stop the warning about the api not properly + # being setup. This is in the event that the keys.dat is in a different + # directory or is created locally to connect to a machine remotely. + BMConfigParser().set('bitmessagesettings', 'port', '8444') + BMConfigParser().set('bitmessagesettings', 'apienabled', 'true') # Sets apienabled to true in keys.dat + with open(keysName, 'wb') as configfile: BMConfigParser().write(configfile) print '\n ' + str(keysName) + ' Initalized in the same directory as daemon.py' print ' You will now need to configure the ' + str(keysName) + ' file.\n' + def apiInit(apiEnabled): + """Initialise the API""" + global usrPrompt BMConfigParser().read(keysPath) - - - if (apiEnabled == False): #API information there but the api is disabled. + if apiEnabled is False: # API information there but the api is disabled. uInput = userInput("The API is not enabled. Would you like to do that now, (Y)es or (N)o?").lower() - if uInput == "y": # - BMConfigParser().set('bitmessagesettings','apienabled','true') #Sets apienabled to true in keys.dat + if uInput == "y": + BMConfigParser().set('bitmessagesettings', 'apienabled', 'true') # Sets apienabled to true in keys.dat with open(keysPath, 'wb') as configfile: BMConfigParser().write(configfile) - + print 'Done' restartBmNotify() return True - + elif uInput == "n": print ' \n************************************************************' print ' Daemon will not work when the API is disabled. ' @@ -100,25 +125,25 @@ def apiInit(apiEnabled): print ' ************************************************************\n' usrPrompt = 1 main() - + else: print '\n Invalid Entry\n' usrPrompt = 1 main() - elif (apiEnabled == True): #API correctly setup - #Everything is as it should be + + elif apiEnabled: # API correctly setup + # Everything is as it should be return True - - else: #API information was not present. + + else: # API information was not present. print '\n ' + str(keysPath) + ' not properly configured!\n' uInput = userInput("Would you like to do this now, (Y)es or (N)o?").lower() - if uInput == "y": #User said yes, initalize the api by writing these values to the keys.dat file + if uInput == "y": # User said yes, initalize the api by writing these values to the keys.dat file print ' ' - + apiUsr = userInput("API Username") apiPwd = userInput("API Password") - #apiInterface = userInput("API Interface. (127.0.0.1)") apiPort = userInput("API Port") apiEnabled = userInput("API Enabled? (True) or (False)").lower() daemon = userInput("Daemon mode Enabled? (True) or (False)").lower() @@ -127,11 +152,14 @@ def apiInit(apiEnabled): print '\n Invalid Entry for Daemon.\n' uInput = 1 main() - + print ' -----------------------------------\n' - - BMConfigParser().set('bitmessagesettings', 'port', '8444') #sets the bitmessage port to stop the warning about the api not properly being setup. This is in the event that the keys.dat is in a different directory or is created locally to connect to a machine remotely. - BMConfigParser().set('bitmessagesettings','apienabled','true') + + # sets the bitmessage port to stop the warning about the api not properly + # being setup. This is in the event that the keys.dat is in a different + # directory or is created locally to connect to a machine remotely. + BMConfigParser().set('bitmessagesettings', 'port', '8444') + BMConfigParser().set('bitmessagesettings', 'apienabled', 'true') BMConfigParser().set('bitmessagesettings', 'apiport', apiPort) BMConfigParser().set('bitmessagesettings', 'apiinterface', '127.0.0.1') BMConfigParser().set('bitmessagesettings', 'apiusername', apiUsr) @@ -139,11 +167,11 @@ def apiInit(apiEnabled): BMConfigParser().set('bitmessagesettings', 'daemon', daemon) with open(keysPath, 'wb') as configfile: BMConfigParser().write(configfile) - + print '\n Finished configuring the keys.dat file with API information.\n' restartBmNotify() return True - + elif uInput == "n": print '\n ***********************************************************' print ' Please refer to the Bitmessage Wiki on how to setup the API.' @@ -157,25 +185,27 @@ def apiInit(apiEnabled): def apiData(): + """TBC""" + global keysName global keysPath global usrPrompt - - BMConfigParser().read(keysPath) #First try to load the config file (the keys.dat file) from the program directory + + BMConfigParser().read(keysPath) # First try to load the config file (the keys.dat file) from the program directory try: - BMConfigParser().get('bitmessagesettings','port') + BMConfigParser().get('bitmessagesettings', 'port') appDataFolder = '' except: - #Could not load the keys.dat file in the program directory. Perhaps it is in the appdata directory. + # Could not load the keys.dat file in the program directory. Perhaps it is in the appdata directory. appDataFolder = lookupAppdataFolder() keysPath = appDataFolder + keysPath BMConfigParser().read(keysPath) try: - BMConfigParser().get('bitmessagesettings','port') + BMConfigParser().get('bitmessagesettings', 'port') except: - #keys.dat was not there either, something is wrong. + # keys.dat was not there either, something is wrong. print '\n ******************************************************************' print ' There was a problem trying to access the Bitmessage keys.dat file' print ' or keys.dat is not set up correctly' @@ -183,7 +213,7 @@ def apiData(): print ' ******************************************************************\n' uInput = userInput("Would you like to create a keys.dat in the local directory, (Y)es or (N)o?").lower() - + if (uInput == "y" or uInput == "yes"): configInit() keysPath = keysName @@ -199,55 +229,62 @@ def apiData(): usrPrompt = 1 main() - try: #checks to make sure that everyting is configured correctly. Excluding apiEnabled, it is checked after + try: # checks to make sure that everyting is configured correctly. Excluding apiEnabled, it is checked after BMConfigParser().get('bitmessagesettings', 'apiport') BMConfigParser().get('bitmessagesettings', 'apiinterface') BMConfigParser().get('bitmessagesettings', 'apiusername') BMConfigParser().get('bitmessagesettings', 'apipassword') + except: - apiInit("") #Initalize the keys.dat file with API information + apiInit("") # Initalize the keys.dat file with API information - #keys.dat file was found or appropriately configured, allow information retrieval - #apiEnabled = apiInit(BMConfigParser().safeGetBoolean('bitmessagesettings','apienabled')) #if false it will prompt the user, if true it will return true + # keys.dat file was found or appropriately configured, allow information retrieval + # apiEnabled = + # apiInit(BMConfigParser().safeGetBoolean('bitmessagesettings','apienabled')) + # #if false it will prompt the user, if true it will return true - BMConfigParser().read(keysPath)#read again since changes have been made + BMConfigParser().read(keysPath) # read again since changes have been made apiPort = int(BMConfigParser().get('bitmessagesettings', 'apiport')) apiInterface = BMConfigParser().get('bitmessagesettings', 'apiinterface') apiUsername = BMConfigParser().get('bitmessagesettings', 'apiusername') apiPassword = BMConfigParser().get('bitmessagesettings', 'apipassword') - + print '\n API data successfully imported.\n' - - return "http://" + apiUsername + ":" + apiPassword + "@" + apiInterface+ ":" + str(apiPort) + "/" #Build the api credentials - -#End keys.dat interactions + + # Build the api credentials + return "http://" + apiUsername + ":" + apiPassword + "@" + apiInterface + ":" + str(apiPort) + "/" -def apiTest(): #Tests the API connection to bitmessage. Returns true if it is connected. +# End keys.dat interactions + + +def apiTest(): + """Tests the API connection to bitmessage. Returns true if it is connected.""" try: - result = api.add(2,3) + result = api.add(2, 3) except: return False - if (result == 5): - return True - else: - return False + return result == 5 + + +def bmSettings(): + """Allows the viewing and modification of keys.dat settings.""" -def bmSettings(): #Allows the viewing and modification of keys.dat settings. global keysPath global usrPrompt + keysPath = 'keys.dat' - - BMConfigParser().read(keysPath)#Read the keys.dat + + BMConfigParser().read(keysPath) # Read the keys.dat try: port = BMConfigParser().get('bitmessagesettings', 'port') except: print '\n File not found.\n' usrPrompt = 0 main() - + startonlogon = BMConfigParser().safeGetBoolean('bitmessagesettings', 'startonlogon') minimizetotray = BMConfigParser().safeGetBoolean('bitmessagesettings', 'minimizetotray') showtraynotifications = BMConfigParser().safeGetBoolean('bitmessagesettings', 'showtraynotifications') @@ -263,7 +300,6 @@ def bmSettings(): #Allows the viewing and modification of keys.dat settings. socksusername = BMConfigParser().get('bitmessagesettings', 'socksusername') sockspassword = BMConfigParser().get('bitmessagesettings', 'sockspassword') - print '\n -----------------------------------' print ' | Current Bitmessage Settings |' print ' -----------------------------------' @@ -287,9 +323,9 @@ def bmSettings(): #Allows the viewing and modification of keys.dat settings. print ' ' uInput = userInput("Would you like to modify any of these settings, (Y)es or (N)o?").lower() - + if uInput == "y": - while True: #loops if they mistype the setting name, they can exit the loop with 'exit' + while True: # loops if they mistype the setting name, they can exit the loop with 'exit' invalidInput = False uInput = userInput("What setting would you like to modify?").lower() print ' ' @@ -354,8 +390,8 @@ def bmSettings(): #Allows the viewing and modification of keys.dat settings. else: print "\n Invalid input. Please try again.\n" invalidInput = True - - if invalidInput != True: #don't prompt if they made a mistake. + + if invalidInput is not True: # don't prompt if they made a mistake. uInput = userInput("Would you like to change another setting, (Y)es or (N)o?").lower() if uInput != "y": @@ -364,8 +400,7 @@ def bmSettings(): #Allows the viewing and modification of keys.dat settings. BMConfigParser().write(configfile) restartBmNotify() break - - + elif uInput == "n": usrPrompt = 1 main() @@ -374,65 +409,70 @@ def bmSettings(): #Allows the viewing and modification of keys.dat settings. usrPrompt = 1 main() + def validAddress(address): + """Predicate to test address validity""" address_information = json.loads(api.decodeAddress(address)) - - if 'success' in str(address_information['status']).lower(): - return True - else: - return False -def getAddress(passphrase,vNumber,sNumber): - passphrase = passphrase.encode('base64')#passphrase must be encoded + return 'success' in str(address_information['status']).lower() + + +def getAddress(passphrase, vNumber, sNumber): + """Get a deterministic address""" + passphrase = passphrase.encode('base64') # passphrase must be encoded + + return api.getDeterministicAddress(passphrase, vNumber, sNumber) - return api.getDeterministicAddress(passphrase,vNumber,sNumber) def subscribe(): + """Subscribe to an address""" global usrPrompt while True: address = userInput("What address would you like to subscribe to?") - if (address == "c"): - usrPrompt = 1 - print ' ' - main() - elif (validAddress(address)== False): + if address == "c": + usrPrompt = 1 + print ' ' + main() + elif validAddress(address) is False: print '\n Invalid. "c" to cancel. Please try again.\n' else: break - + label = userInput("Enter a label for this address.") label = label.encode('base64') - - api.addSubscription(address,label) - print ('\n You are now subscribed to: ' + address + '\n') + + api.addSubscription(address, label) + print '\n You are now subscribed to: ' + address + '\n' + def unsubscribe(): + """Unsusbcribe from an address""" global usrPrompt - + while True: address = userInput("What address would you like to unsubscribe from?") - if (address == "c"): - usrPrompt = 1 - print ' ' - main() - elif (validAddress(address)== False): + if address == "c": + usrPrompt = 1 + print ' ' + main() + elif validAddress(address) is False: print '\n Invalid. "c" to cancel. Please try again.\n' else: break - - - userInput("Are you sure, (Y)es or (N)o?").lower() # #uInput = - + + userInput("Are you sure, (Y)es or (N)o?").lower() # uInput = + api.deleteSubscription(address) - print ('\n You are now unsubscribed from: ' + address + '\n') + print '\n You are now unsubscribed from: ' + address + '\n' + def listSubscriptions(): + """List subscriptions""" + global usrPrompt - #jsonAddresses = json.loads(api.listSubscriptions()) - #numAddresses = len(jsonAddresses['addresses']) #Number of addresses print '\nLabel, Address, Enabled\n' try: print api.listSubscriptions() @@ -440,17 +480,12 @@ def listSubscriptions(): print '\n Connection Error\n' usrPrompt = 0 main() - - '''for addNum in range (0, numAddresses): #processes all of the addresses and lists them out - label = jsonAddresses['addresses'][addNum]['label'] - address = jsonAddresses['addresses'][addNum]['address'] - enabled = jsonAddresses['addresses'][addNum]['enabled'] - - print label, address, enabled - ''' print ' ' + def createChan(): + """Create a channel""" + global usrPrompt password = userInput("Enter channel name") password = password.encode('base64') @@ -463,42 +498,47 @@ def createChan(): def joinChan(): + """Join a channel""" + global usrPrompt while True: address = userInput("Enter channel address") - - if (address == "c"): - usrPrompt = 1 - print ' ' - main() - elif (validAddress(address)== False): + + if address == "c": + usrPrompt = 1 + print ' ' + main() + elif validAddress(address) is False: print '\n Invalid. "c" to cancel. Please try again.\n' else: break - + password = userInput("Enter channel name") password = password.encode('base64') try: - print api.joinChan(password,address) + print api.joinChan(password, address) except: print '\n Connection Error\n' usrPrompt = 0 main() + def leaveChan(): + """Leave a channel""" + global usrPrompt while True: address = userInput("Enter channel address") - - if (address == "c"): - usrPrompt = 1 - print ' ' - main() - elif (validAddress(address)== False): + + if address == "c": + usrPrompt = 1 + print ' ' + main() + elif validAddress(address) is False: print '\n Invalid. "c" to cancel. Please try again.\n' else: break - + try: print api.leaveChan(address) except: @@ -507,36 +547,58 @@ def leaveChan(): main() -def listAdd(): #Lists all of the addresses and their info +def listAdd(): + """List all of the addresses and their info""" global usrPrompt try: jsonAddresses = json.loads(api.listAddresses()) - numAddresses = len(jsonAddresses['addresses']) #Number of addresses + numAddresses = len(jsonAddresses['addresses']) # Number of addresses except: print '\n Connection Error\n' usrPrompt = 0 main() - #print '\nAddress Number,Label,Address,Stream,Enabled\n' + # print '\nAddress Number,Label,Address,Stream,Enabled\n' print '\n --------------------------------------------------------------------------' print ' | # | Label | Address |S#|Enabled|' print ' |---|-------------------|-------------------------------------|--|-------|' - for addNum in range (0, numAddresses): #processes all of the addresses and lists them out - label = (jsonAddresses['addresses'][addNum]['label' ]).encode('utf') # may still misdiplay in some consoles + for addNum in range(0, numAddresses): # processes all of the addresses and lists them out + label = (jsonAddresses['addresses'][addNum]['label']).encode( + 'utf') # may still misdiplay in some consoles address = str(jsonAddresses['addresses'][addNum]['address']) - stream = str(jsonAddresses['addresses'][addNum]['stream']) + stream = str(jsonAddresses['addresses'][addNum]['stream']) enabled = str(jsonAddresses['addresses'][addNum]['enabled']) - if (len(label) > 19): + if len(label) > 19: label = label[:16] + '...' - - print ' |' + str(addNum).ljust(3) + '|' + label.ljust(19) + '|' + address.ljust(37) + '|' + stream.ljust(1), '|' + enabled.ljust(7) + '|' - print ' --------------------------------------------------------------------------\n' + print ''.join( + ' |', + str(addNum).ljust(3), + '|', + label.ljust(19), + '|', + address.ljust(37), + '|', + stream.ljust(1), + '|', + enabled.ljust(7), + '|', + ) + + print ''.join( + ' ', + 74 * '-', + '\n', + ) + + +def genAdd(lbl, deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe): + """Generate address""" -def genAdd(lbl,deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe): #Generate address global usrPrompt - if deterministic == False: #Generates a new address with the user defined label. non-deterministic + + if deterministic is False: # Generates a new address with the user defined label. non-deterministic addressLabel = lbl.encode('base64') try: generatedAddress = api.createRandomAddress(addressLabel) @@ -544,10 +606,10 @@ def genAdd(lbl,deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe): # print '\n Connection Error\n' usrPrompt = 0 main() - + return generatedAddress - - elif deterministic == True: #Generates a new deterministic address with the user inputs. + + elif deterministic: # Generates a new deterministic address with the user inputs. passphrase = passphrase.encode('base64') try: generatedAddress = api.createDeterministicAddresses(passphrase, numOfAdd, addVNum, streamNum, ripe) @@ -556,55 +618,17 @@ def genAdd(lbl,deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe): # usrPrompt = 0 main() return generatedAddress - else: - return 'Entry Error' -def delMilAddr(): #Delete address - global usrPrompt - try: - response = api.listAddresses2() - # if api is too old just return then fail - if "API Error 0020" in response: return - addresses = json.loads(response) - for entry in addresses['addresses']: - if entry['label'].decode('base64')[:6] == "random": - api.deleteAddress(entry['address']) - except: - print '\n Connection Error\n' - usrPrompt = 0 - main() + return 'Entry Error' -def genMilAddr(): #Generate address - global usrPrompt - maxn = 0 - try: - response = api.listAddresses2() - if "API Error 0020" in response: return - addresses = json.loads(response) - for entry in addresses['addresses']: - if entry['label'].decode('base64')[:6] == "random": - newn = int(entry['label'].decode('base64')[6:]) - if maxn < newn: - maxn = newn - except: - print "\n Some error\n" - print "\n Starting at " + str(maxn) + "\n" - for i in range(maxn, 10000): - lbl = "random" + str(i) - addressLabel = lbl.encode('base64') - try: - api.createRandomAddress(addressLabel) # generatedAddress = - except: - print '\n Connection Error\n' - usrPrompt = 0 - main() -def saveFile(fileName, fileData): #Allows attachments and messages/broadcats to be saved +def saveFile(fileName, fileData): + """Allows attachments and messages/broadcats to be saved""" - #This section finds all invalid characters and replaces them with ~ + # This section finds all invalid characters and replaces them with ~ fileName = fileName.replace(" ", "") fileName = fileName.replace("/", "~") - #fileName = fileName.replace("\\", "~") How do I get this to work...? + # fileName = fileName.replace("\\", "~") How do I get this to work...? fileName = fileName.replace(":", "~") fileName = fileName.replace("*", "~") fileName = fileName.replace("?", "~") @@ -613,63 +637,62 @@ def saveFile(fileName, fileData): #Allows attachments and messages/broadcats to fileName = fileName.replace(">", "~") fileName = fileName.replace("|", "~") - directory = 'attachments' + directory = os.path.abspath('attachments') if not os.path.exists(directory): os.makedirs(directory) - - filePath = directory +'/'+ fileName - '''try: #Checks if file already exists - with open(filePath): - print 'File Already Exists' - return - except IOError: pass''' + filePath = os.path.join(directory, fileName) + + with open(filePath, 'wb+') as path_to_file: + path_to_file.write(fileData.decode("base64")) + print '\n Successfully saved ' + filePath + '\n' - f = open(filePath, 'wb+') #Begin saving to file - f.write(fileData.decode("base64")) - f.close +def attachment(): + """Allows users to attach a file to their message or broadcast""" - print '\n Successfully saved '+ filePath + '\n' - -def attachment(): #Allows users to attach a file to their message or broadcast theAttachmentS = '' - + while True: isImage = False theAttachment = '' - - while True:#loops until valid path is entered - filePath = userInput('\nPlease enter the path to the attachment or just the attachment name if in this folder.') + + while True: # loops until valid path is entered + filePath = userInput( + '\nPlease enter the path to the attachment or just the attachment name if in this folder.') try: - with open(filePath): break + with open(filePath): + break except IOError: print '\n %s was not found on your filesystem or can not be opened.\n' % filePath - pass - #print filesize, and encoding estimate with confirmation if file is over X size (1mb?) + # print filesize, and encoding estimate with confirmation if file is over X size (1mb?) invSize = os.path.getsize(filePath) - invSize = (invSize / 1024) #Converts to kilobytes - round(invSize,2) #Rounds to two decimal places + invSize = (invSize / 1024) # Converts to kilobytes + round(invSize, 2) # Rounds to two decimal places - if (invSize > 500.0):#If over 500KB - print '\n WARNING:The file that you are trying to attach is ', invSize, 'KB and will take considerable time to send.\n' + if invSize > 500.0: # If over 500KB + print ''.join( + '\n WARNING:The file that you are trying to attach is ', + invSize, + 'KB and will take considerable time to send.\n' + ) uInput = userInput('Are you sure you still want to attach it, (Y)es or (N)o?').lower() if uInput != "y": print '\n Attachment discarded.\n' return '' - elif (invSize > 184320.0): #If larger than 180MB, discard. + elif invSize > 184320.0: # If larger than 180MB, discard. print '\n Attachment too big, maximum allowed size:180MB\n' main() - - pathLen = len(str(ntpath.basename(filePath))) #Gets the length of the filepath excluding the filename - fileName = filePath[(len(str(filePath)) - pathLen):] #reads the filename - - filetype = imghdr.what(filePath) #Tests if it is an image file + + pathLen = len(str(ntpath.basename(filePath))) # Gets the length of the filepath excluding the filename + fileName = filePath[(len(str(filePath)) - pathLen):] # reads the filename + + filetype = imghdr.what(filePath) # Tests if it is an image file if filetype is not None: print '\n ---------------------------------------------------' print ' Attachment detected as an Image.' @@ -679,74 +702,80 @@ def attachment(): #Allows users to attach a file to their message or broadcast print ' ---------------------------------------------------\n' isImage = True time.sleep(2) - - print '\n Encoding Attachment, Please Wait ...\n' #Alert the user that the encoding process may take some time. - - with open(filePath, 'rb') as f: #Begin the actual encoding - data = f.read(188743680) #Reads files up to 180MB, the maximum size for Bitmessage. + + # Alert the user that the encoding process may take some time. + print '\n Encoding Attachment, Please Wait ...\n' + + with open(filePath, 'rb') as f: # Begin the actual encoding + data = f.read(188743680) # Reads files up to 180MB, the maximum size for Bitmessage. data = data.encode("base64") - if (isImage == True): #If it is an image, include image tags in the message + if isImage: # If it is an image, include image tags in the message theAttachment = """ - -Filename:%s -Filesize:%sKB -Encoding:base64 - + +Filename:%s +Filesize:%sKB +Encoding:base64 +
%s
-
""" % (fileName,invSize,fileName,filetype,data) - else: #Else it is not an image so do not include the embedded image code. +""" % (fileName, invSize, fileName, filetype, data) + else: # Else it is not an image so do not include the embedded image code. theAttachment = """ - -Filename:%s -Filesize:%sKB -Encoding:base64 - -""" % (fileName,invSize,fileName,fileName,data) + +Filename:%s +Filesize:%sKB +Encoding:base64 + +""" % (fileName, invSize, fileName, fileName, data) uInput = userInput('Would you like to add another attachment, (Y)es or (N)o?').lower() - if (uInput == 'y' or uInput == 'yes'):#Allows multiple attachments to be added to one message - theAttachmentS = str(theAttachmentS) + str(theAttachment)+ '\n\n' - elif (uInput == 'n' or uInput == 'no'): + if uInput == 'y' or uInput == 'yes': # Allows multiple attachments to be added to one message + theAttachmentS = str(theAttachmentS) + str(theAttachment) + '\n\n' + elif uInput == 'n' or uInput == 'no': break - + theAttachmentS = theAttachmentS + theAttachment return theAttachmentS -def sendMsg(toAddress, fromAddress, subject, message): #With no arguments sent, sendMsg fills in the blanks. subject and message must be encoded before they are passed. + +def sendMsg(toAddress, fromAddress, subject, message): + """ + With no arguments sent, sendMsg fills in the blanks. + subject and message must be encoded before they are passed. + """ + global usrPrompt - if (validAddress(toAddress)== False): + if validAddress(toAddress) is False: while True: toAddress = userInput("What is the To Address?") - if (toAddress == "c"): + if toAddress == "c": usrPrompt = 1 print ' ' main() - elif (validAddress(toAddress)== False): + elif validAddress(toAddress) is False: print '\n Invalid Address. "c" to cancel. Please try again.\n' else: break - - - if (validAddress(fromAddress)== False): - try: + + if validAddress(fromAddress) is False: + try: jsonAddresses = json.loads(api.listAddresses()) - numAddresses = len(jsonAddresses['addresses']) #Number of addresses + numAddresses = len(jsonAddresses['addresses']) # Number of addresses except: print '\n Connection Error\n' usrPrompt = 0 main() - - if (numAddresses > 1): #Ask what address to send from if multiple addresses + + if numAddresses > 1: # Ask what address to send from if multiple addresses found = False while True: print ' ' @@ -756,52 +785,47 @@ def sendMsg(toAddress, fromAddress, subject, message): #With no arguments sent, usrPrompt = 1 main() - for addNum in range (0, numAddresses): #processes all of the addresses + for addNum in range(0, numAddresses): # processes all of the addresses label = jsonAddresses['addresses'][addNum]['label'] address = jsonAddresses['addresses'][addNum]['address'] - #stream = jsonAddresses['addresses'][addNum]['stream'] - #enabled = jsonAddresses['addresses'][addNum]['enabled'] - if (fromAddress == label): #address entered was a label and is found + if fromAddress == label: # address entered was a label and is found fromAddress = address found = True break - - if (found == False): - if(validAddress(fromAddress)== False): + + if found is False: + if validAddress(fromAddress) is False: print '\n Invalid Address. Please try again.\n' - + else: - for addNum in range (0, numAddresses): #processes all of the addresses - #label = jsonAddresses['addresses'][addNum]['label'] + for addNum in range(0, numAddresses): # processes all of the addresses address = jsonAddresses['addresses'][addNum]['address'] - #stream = jsonAddresses['addresses'][addNum]['stream'] - #enabled = jsonAddresses['addresses'][addNum]['enabled'] - if (fromAddress == address): #address entered was a found in our addressbook. + if fromAddress == address: # address entered was a found in our addressbook. found = True break - - if (found == False): + + if found is False: print '\n The address entered is not one of yours. Please try again.\n' - - if (found == True): - break #Address was found - - else: #Only one address in address book + + if found: + break # Address was found + + else: # Only one address in address book print '\n Using the only address in the addressbook to send from.\n' fromAddress = jsonAddresses['addresses'][0]['address'] - if (subject == ''): + if subject == '': subject = userInput("Enter your Subject.") subject = subject.encode('base64') - if (message == ''): + if message == '': message = userInput("Enter your Message.") uInput = userInput('Would you like to add an attachment, (Y)es or (N)o?').lower() if uInput == "y": message = message + '\n\n' + attachment() - + message = message.encode('base64') - + try: ackData = api.sendMessage(toAddress, fromAddress, subject, message) print '\n Message Status:', api.getStatus(ackData), '\n' @@ -811,19 +835,21 @@ def sendMsg(toAddress, fromAddress, subject, message): #With no arguments sent, main() -def sendBrd(fromAddress, subject, message): #sends a broadcast +def sendBrd(fromAddress, subject, message): + """Send a broadcast""" + global usrPrompt - if (fromAddress == ''): + if fromAddress == '': try: jsonAddresses = json.loads(api.listAddresses()) - numAddresses = len(jsonAddresses['addresses']) #Number of addresses + numAddresses = len(jsonAddresses['addresses']) # Number of addresses except: print '\n Connection Error\n' usrPrompt = 0 main() - - if (numAddresses > 1): #Ask what address to send from if multiple addresses + + if numAddresses > 1: # Ask what address to send from if multiple addresses found = False while True: fromAddress = userInput("\nEnter an Address or Address Label to send from.") @@ -832,51 +858,46 @@ def sendBrd(fromAddress, subject, message): #sends a broadcast usrPrompt = 1 main() - for addNum in range (0, numAddresses): #processes all of the addresses + for addNum in range(0, numAddresses): # processes all of the addresses label = jsonAddresses['addresses'][addNum]['label'] address = jsonAddresses['addresses'][addNum]['address'] - #stream = jsonAddresses['addresses'][addNum]['stream'] - #enabled = jsonAddresses['addresses'][addNum]['enabled'] - if (fromAddress == label): #address entered was a label and is found + if fromAddress == label: # address entered was a label and is found fromAddress = address found = True break - - if (found == False): - if(validAddress(fromAddress)== False): + + if found is False: + if validAddress(fromAddress) is False: print '\n Invalid Address. Please try again.\n' - + else: - for addNum in range (0, numAddresses): #processes all of the addresses - #label = jsonAddresses['addresses'][addNum]['label'] + for addNum in range(0, numAddresses): # processes all of the addresses address = jsonAddresses['addresses'][addNum]['address'] - #stream = jsonAddresses['addresses'][addNum]['stream'] - #enabled = jsonAddresses['addresses'][addNum]['enabled'] - if (fromAddress == address): #address entered was a found in our addressbook. + if fromAddress == address: # address entered was a found in our addressbook. found = True break - - if (found == False): + + if found is False: print '\n The address entered is not one of yours. Please try again.\n' - - if (found == True): - break #Address was found - - else: #Only one address in address book + + if found: + break # Address was found + + else: # Only one address in address book print '\n Using the only address in the addressbook to send from.\n' fromAddress = jsonAddresses['addresses'][0]['address'] - if (subject == ''): - subject = userInput("Enter your Subject.") - subject = subject.encode('base64') - if (message == ''): - message = userInput("Enter your Message.") + if subject == '': + subject = userInput("Enter your Subject.") + subject = subject.encode('base64') + if message == '': + message = userInput("Enter your Message.") - uInput = userInput('Would you like to add an attachment, (Y)es or (N)o?').lower() - if uInput == "y": - message = message + '\n\n' + attachment() - - message = message.encode('base64') + uInput = userInput('Would you like to add an attachment, (Y)es or (N)o?').lower() + if uInput == "y": + message = message + '\n\n' + attachment() + + message = message.encode('base64') try: ackData = api.sendBroadcast(fromAddress, subject, message) @@ -886,7 +907,10 @@ def sendBrd(fromAddress, subject, message): #sends a broadcast usrPrompt = 0 main() -def inbox(unreadOnly = False): #Lists the messages by: Message Number, To Address Label, From Address Label, Subject, Received Time) + +def inbox(unreadOnly=False): + """Lists the messages by: Message Number, To Address Label, From Address Label, Subject, Received Time)""" + global usrPrompt try: inboxMessages = json.loads(api.getAllInboxMessages()) @@ -898,27 +922,35 @@ def inbox(unreadOnly = False): #Lists the messages by: Message Number, To Addres messagesPrinted = 0 messagesUnread = 0 - for msgNum in range (0, numMessages): #processes all of the messages in the inbox + for msgNum in range(0, numMessages): # processes all of the messages in the inbox message = inboxMessages['inboxMessages'][msgNum] # if we are displaying all messages or if this message is unread then display it if not unreadOnly or not message['read']: print ' -----------------------------------\n' - print ' Message Number:',msgNum #Message Number - print ' To:', getLabelForAddress(message['toAddress']) #Get the to address - print ' From:', getLabelForAddress(message['fromAddress']) #Get the from address - print ' Subject:', message['subject'].decode('base64') #Get the subject - print ' Received:', datetime.datetime.fromtimestamp(float(message['receivedTime'])).strftime('%Y-%m-%d %H:%M:%S') + print ' Message Number:', msgNum # Message Number + print ' To:', getLabelForAddress(message['toAddress']) # Get the to address + print ' From:', getLabelForAddress(message['fromAddress']) # Get the from address + print ' Subject:', message['subject'].decode('base64') # Get the subject + print ''.join( + ' Received:', + datetime.datetime.fromtimestamp( + float(message['receivedTime'])).strftime('%Y-%m-%d %H:%M:%S'), + ) messagesPrinted += 1 - if not message['read']: messagesUnread += 1 + if not message['read']: + messagesUnread += 1 + + if messagesPrinted % 20 == 0 and messagesPrinted != 0: + userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower() # uInput = - if (messagesPrinted%20 == 0 and messagesPrinted != 0): - userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower() # uInput = - print '\n -----------------------------------' print ' There are %d unread messages of %d messages in the inbox.' % (messagesUnread, numMessages) print ' -----------------------------------\n' + def outbox(): + """TBC""" + global usrPrompt try: outboxMessages = json.loads(api.getAllSentMessages()) @@ -928,25 +960,33 @@ def outbox(): usrPrompt = 0 main() - for msgNum in range (0, numMessages): #processes all of the messages in the outbox + for msgNum in range(0, numMessages): # processes all of the messages in the outbox print '\n -----------------------------------\n' - print ' Message Number:',msgNum #Message Number - #print ' Message ID:', outboxMessages['sentMessages'][msgNum]['msgid'] - print ' To:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['toAddress']) #Get the to address - print ' From:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['fromAddress']) #Get the from address - print ' Subject:', outboxMessages['sentMessages'][msgNum]['subject'].decode('base64') #Get the subject - print ' Status:', outboxMessages['sentMessages'][msgNum]['status'] #Get the subject - - print ' Last Action Time:', datetime.datetime.fromtimestamp(float(outboxMessages['sentMessages'][msgNum]['lastActionTime'])).strftime('%Y-%m-%d %H:%M:%S') + print ' Message Number:', msgNum # Message Number + # print ' Message ID:', outboxMessages['sentMessages'][msgNum]['msgid'] + print ' To:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['toAddress']) # Get the to address + # Get the from address + print ' From:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['fromAddress']) + print ' Subject:', outboxMessages['sentMessages'][msgNum]['subject'].decode('base64') # Get the subject + print ' Status:', outboxMessages['sentMessages'][msgNum]['status'] # Get the subject - if (msgNum%20 == 0 and msgNum != 0): - userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower() # uInput = + print ''.join( + ' Last Action Time:', + datetime.datetime.fromtimestamp( + float(outboxMessages['sentMessages'][msgNum]['lastActionTime'])).strftime('%Y-%m-%d %H:%M:%S'), + ) + + if msgNum % 20 == 0 and msgNum != 0: + userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower() # uInput = print '\n -----------------------------------' - print ' There are ',numMessages,' messages in the outbox.' + print ' There are ', numMessages, ' messages in the outbox.' print ' -----------------------------------\n' -def readSentMsg(msgNum): #Opens a sent message for reading + +def readSentMsg(msgNum): + """Opens a sent message for reading""" + global usrPrompt try: outboxMessages = json.loads(api.getAllSentMessages()) @@ -955,56 +995,63 @@ def readSentMsg(msgNum): #Opens a sent message for reading print '\n Connection Error\n' usrPrompt = 0 main() - + print ' ' - if (msgNum >= numMessages): + if msgNum >= numMessages: print '\n Invalid Message Number.\n' main() - #Begin attachment detection + # Begin attachment detection message = outboxMessages['sentMessages'][msgNum]['message'].decode('base64') - while True: #Allows multiple messages to be downloaded/saved - if (';base64,' in message): #Found this text in the message, there is probably an attachment. - attPos= message.index(";base64,") #Finds the attachment position - attEndPos = message.index("' />") #Finds the end of the attachment - #attLen = attEndPos - attPos #Finds the length of the message + while True: # Allows multiple messages to be downloaded/saved + if ';base64,' in message: # Found this text in the message, there is probably an attachment. + attPos = message.index(";base64,") # Finds the attachment position + attEndPos = message.index("' />") # Finds the end of the attachment + # attLen = attEndPos - attPos #Finds the length of the message + if 'alt = "' in message: # We can get the filename too + fnPos = message.index('alt = "') # Finds position of the filename + fnEndPos = message.index('" src=') # Finds the end position + # fnLen = fnEndPos - fnPos #Finds the length of the filename - if ('alt = "' in message): #We can get the filename too - fnPos = message.index('alt = "') #Finds position of the filename - fnEndPos = message.index('" src=') #Finds the end position - #fnLen = fnEndPos - fnPos #Finds the length of the filename - - fileName = message[fnPos+7:fnEndPos] + fileName = message[fnPos + 7:fnEndPos] else: fnPos = attPos fileName = 'Attachment' - uInput = userInput('\n Attachment Detected. Would you like to save the attachment, (Y)es or (N)o?').lower() - if (uInput == "y" or uInput == 'yes'): - - attachment = message[attPos+9:attEndPos] - saveFile(fileName,attachment) + uInput = userInput( + '\n Attachment Detected. Would you like to save the attachment, (Y)es or (N)o?').lower() + if uInput == "y" or uInput == 'yes': - message = message[:fnPos] + '~~' + message[(attEndPos+4):] + this_attachment = message[attPos + 9:attEndPos] + saveFile(fileName, this_attachment) + + message = message[:fnPos] + '~~' + message[(attEndPos + 4):] else: break - - #End attachment Detection - - print '\n To:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['toAddress']) #Get the to address - print ' From:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['fromAddress']) #Get the from address - print ' Subject:', outboxMessages['sentMessages'][msgNum]['subject'].decode('base64') #Get the subject - print ' Status:', outboxMessages['sentMessages'][msgNum]['status'] #Get the subject - print ' Last Action Time:', datetime.datetime.fromtimestamp(float(outboxMessages['sentMessages'][msgNum]['lastActionTime'])).strftime('%Y-%m-%d %H:%M:%S') + + # End attachment Detection + + print '\n To:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['toAddress']) # Get the to address + # Get the from address + print ' From:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['fromAddress']) + print ' Subject:', outboxMessages['sentMessages'][msgNum]['subject'].decode('base64') # Get the subject + print ' Status:', outboxMessages['sentMessages'][msgNum]['status'] # Get the subject + print ''.join( + ' Last Action Time:', + datetime.datetime.fromtimestamp( + float(outboxMessages['sentMessages'][msgNum]['lastActionTime'])).strftime('%Y-%m-%d %H:%M:%S'), + ) print ' Message:\n' - print message #inboxMessages['inboxMessages'][msgNum]['message'].decode('base64') + print message # inboxMessages['inboxMessages'][msgNum]['message'].decode('base64') print ' ' -def readMsg(msgNum): #Opens a message for reading + +def readMsg(msgNum): + """Open a message for reading""" global usrPrompt try: inboxMessages = json.loads(api.getAllInboxMessages()) @@ -1014,82 +1061,89 @@ def readMsg(msgNum): #Opens a message for reading usrPrompt = 0 main() - if (msgNum >= numMessages): + if msgNum >= numMessages: print '\n Invalid Message Number.\n' main() - #Begin attachment detection + # Begin attachment detection message = inboxMessages['inboxMessages'][msgNum]['message'].decode('base64') - while True: #Allows multiple messages to be downloaded/saved - if (';base64,' in message): #Found this text in the message, there is probably an attachment. - attPos= message.index(";base64,") #Finds the attachment position - attEndPos = message.index("' />") #Finds the end of the attachment - #attLen = attEndPos - attPos #Finds the length of the message + while True: # Allows multiple messages to be downloaded/saved + if ';base64,' in message: # Found this text in the message, there is probably an attachment. + attPos = message.index(";base64,") # Finds the attachment position + attEndPos = message.index("' />") # Finds the end of the attachment + # attLen = attEndPos - attPos #Finds the length of the message + if 'alt = "' in message: # We can get the filename too + fnPos = message.index('alt = "') # Finds position of the filename + fnEndPos = message.index('" src=') # Finds the end position + # fnLen = fnEndPos - fnPos #Finds the length of the filename - if ('alt = "' in message): #We can get the filename too - fnPos = message.index('alt = "') #Finds position of the filename - fnEndPos = message.index('" src=') #Finds the end position - #fnLen = fnEndPos - fnPos #Finds the length of the filename - - fileName = message[fnPos+7:fnEndPos] + fileName = message[fnPos + 7:fnEndPos] else: fnPos = attPos fileName = 'Attachment' - uInput = userInput('\n Attachment Detected. Would you like to save the attachment, (Y)es or (N)o?').lower() - if (uInput == "y" or uInput == 'yes'): - - attachment = message[attPos+9:attEndPos] - saveFile(fileName,attachment) + uInput = userInput( + '\n Attachment Detected. Would you like to save the attachment, (Y)es or (N)o?').lower() + if uInput == "y" or uInput == 'yes': - message = message[:fnPos] + '~~' + message[(attEndPos+4):] + this_attachment = message[attPos + 9:attEndPos] + saveFile(fileName, this_attachment) + + message = message[:fnPos] + '~~' + message[attEndPos + 4:] else: break - - #End attachment Detection - print '\n To:', getLabelForAddress(inboxMessages['inboxMessages'][msgNum]['toAddress']) #Get the to address - print ' From:', getLabelForAddress(inboxMessages['inboxMessages'][msgNum]['fromAddress']) #Get the from address - print ' Subject:', inboxMessages['inboxMessages'][msgNum]['subject'].decode('base64') #Get the subject - print ' Received:',datetime.datetime.fromtimestamp(float(inboxMessages['inboxMessages'][msgNum]['receivedTime'])).strftime('%Y-%m-%d %H:%M:%S') + + # End attachment Detection + print '\n To:', getLabelForAddress(inboxMessages['inboxMessages'][msgNum]['toAddress']) # Get the to address + # Get the from address + print ' From:', getLabelForAddress(inboxMessages['inboxMessages'][msgNum]['fromAddress']) + print ' Subject:', inboxMessages['inboxMessages'][msgNum]['subject'].decode('base64') # Get the subject + print ''.join( + ' Received:', datetime.datetime.fromtimestamp( + float(inboxMessages['inboxMessages'][msgNum]['receivedTime'])).strftime('%Y-%m-%d %H:%M:%S'), + ) print ' Message:\n' - print message #inboxMessages['inboxMessages'][msgNum]['message'].decode('base64') + print message # inboxMessages['inboxMessages'][msgNum]['message'].decode('base64') print ' ' return inboxMessages['inboxMessages'][msgNum]['msgid'] -def replyMsg(msgNum,forwardORreply): #Allows you to reply to the message you are currently on. Saves typing in the addresses and subject. + +def replyMsg(msgNum, forwardORreply): + """Allows you to reply to the message you are currently on. Saves typing in the addresses and subject.""" + global usrPrompt - forwardORreply = forwardORreply.lower() #makes it lowercase + forwardORreply = forwardORreply.lower() # makes it lowercase try: inboxMessages = json.loads(api.getAllInboxMessages()) except: print '\n Connection Error\n' usrPrompt = 0 main() - - fromAdd = inboxMessages['inboxMessages'][msgNum]['toAddress']#Address it was sent To, now the From address - message = inboxMessages['inboxMessages'][msgNum]['message'].decode('base64') #Message that you are replying too. - + + fromAdd = inboxMessages['inboxMessages'][msgNum]['toAddress'] # Address it was sent To, now the From address + message = inboxMessages['inboxMessages'][msgNum]['message'].decode('base64') # Message that you are replying too. + subject = inboxMessages['inboxMessages'][msgNum]['subject'] subject = subject.decode('base64') - - if (forwardORreply == 'reply'): - toAdd = inboxMessages['inboxMessages'][msgNum]['fromAddress'] #Address it was From, now the To address + + if forwardORreply == 'reply': + toAdd = inboxMessages['inboxMessages'][msgNum]['fromAddress'] # Address it was From, now the To address subject = "Re: " + subject - - elif (forwardORreply == 'forward'): + + elif forwardORreply == 'forward': subject = "Fwd: " + subject - + while True: toAdd = userInput("What is the To Address?") - if (toAdd == "c"): + if toAdd == "c": usrPrompt = 1 print ' ' main() - elif (validAddress(toAdd)== False): + elif validAddress(toAdd) is False: print '\n Invalid Address. "c" to cancel. Please try again.\n' else: break @@ -1097,51 +1151,62 @@ def replyMsg(msgNum,forwardORreply): #Allows you to reply to the message you are print '\n Invalid Selection. Reply or Forward only' usrPrompt = 0 main() - + subject = subject.encode('base64') - + newMessage = userInput("Enter your Message.") uInput = userInput('Would you like to add an attachment, (Y)es or (N)o?').lower() if uInput == "y": newMessage = newMessage + '\n\n' + attachment() - + newMessage = newMessage + '\n\n------------------------------------------------------\n' newMessage = newMessage + message newMessage = newMessage.encode('base64') sendMsg(toAdd, fromAdd, subject, newMessage) - + main() -def delMsg(msgNum): #Deletes a specified message from the inbox + +def delMsg(msgNum): + """Deletes a specified message from the inbox""" + global usrPrompt try: inboxMessages = json.loads(api.getAllInboxMessages()) - msgId = inboxMessages['inboxMessages'][int(msgNum)]['msgid'] #gets the message ID via the message index number - + # gets the message ID via the message index number + msgId = inboxMessages['inboxMessages'][int(msgNum)]['msgid'] + msgAck = api.trashMessage(msgId) except: print '\n Connection Error\n' usrPrompt = 0 main() - + return msgAck -def delSentMsg(msgNum): #Deletes a specified message from the outbox + +def delSentMsg(msgNum): + """Deletes a specified message from the outbox""" + global usrPrompt try: outboxMessages = json.loads(api.getAllSentMessages()) - msgId = outboxMessages['sentMessages'][int(msgNum)]['msgid'] #gets the message ID via the message index number + # gets the message ID via the message index number + msgId = outboxMessages['sentMessages'][int(msgNum)]['msgid'] msgAck = api.trashSentMessage(msgId) except: print '\n Connection Error\n' usrPrompt = 0 main() - + return msgAck + def getLabelForAddress(address): + """Get label for an address""" + if address in knownAddresses: return knownAddresses[address] else: @@ -1151,12 +1216,18 @@ def getLabelForAddress(address): return address + def buildKnownAddresses(): + """Build known addresses""" + + global usrPrompt + # add from address book try: response = api.listAddressBookEntries() # if api is too old then fail - if "API Error 0020" in response: return + if "API Error 0020" in response: + return addressBook = json.loads(response) for entry in addressBook['addresses']: if entry['address'] not in knownAddresses: @@ -1170,7 +1241,8 @@ def buildKnownAddresses(): try: response = api.listAddresses2() # if api is too old just return then fail - if "API Error 0020" in response: return + if "API Error 0020" in response: + return addresses = json.loads(response) for entry in addresses['addresses']: if entry['address'] not in knownAddresses: @@ -1180,7 +1252,12 @@ def buildKnownAddresses(): usrPrompt = 0 main() + def listAddressBookEntries(): + """List addressbook entries""" + + global usrPrompt + try: response = api.listAddressBookEntries() if "API Error" in response: @@ -1193,7 +1270,8 @@ def listAddressBookEntries(): for entry in addressBook['addresses']: label = entry['label'].decode('base64') address = entry['address'] - if (len(label) > 19): label = label[:16] + '...' + if len(label) > 19: + label = label[:16] + '...' print ' | ' + label.ljust(19) + '| ' + address.ljust(37) + ' |' print ' --------------------------------------------------------------' print @@ -1203,7 +1281,12 @@ def listAddressBookEntries(): usrPrompt = 0 main() + def addAddressToAddressBook(address, label): + """Add an address to an addressbook""" + + global usrPrompt + try: response = api.addAddressBookEntry(address, label.encode('base64')) if "API Error" in response: @@ -1213,7 +1296,12 @@ def addAddressToAddressBook(address, label): usrPrompt = 0 main() + def deleteAddressFromAddressBook(address): + """Delete an address from an addressbook""" + + global usrPrompt + try: response = api.deleteAddressBookEntry(address) if "API Error" in response: @@ -1223,13 +1311,21 @@ def deleteAddressFromAddressBook(address): usrPrompt = 0 main() + def getAPIErrorCode(response): + """Get API error code""" + if "API Error" in response: # if we got an API error return the number by getting the number # after the second space and removing the trailing colon return int(response.split()[2][:-1]) + def markMessageRead(messageID): + """Mark a message as read""" + + global usrPrompt + try: response = api.getInboxMessageByID(messageID, True) if "API Error" in response: @@ -1239,7 +1335,12 @@ def markMessageRead(messageID): usrPrompt = 0 main() + def markMessageUnread(messageID): + """Mark a mesasge as unread""" + + global usrPrompt + try: response = api.getInboxMessageByID(messageID, False) if "API Error" in response: @@ -1249,7 +1350,12 @@ def markMessageUnread(messageID): usrPrompt = 0 main() + def markAllMessagesRead(): + """Mark all messages as read""" + + global usrPrompt + try: inboxMessages = json.loads(api.getAllInboxMessages())['inboxMessages'] except: @@ -1260,7 +1366,12 @@ def markAllMessagesRead(): if not message['read']: markMessageRead(message['msgid']) + def markAllMessagesUnread(): + """Mark all messages as unread""" + + global usrPrompt + try: inboxMessages = json.loads(api.getAllInboxMessages())['inboxMessages'] except: @@ -1271,20 +1382,29 @@ def markAllMessagesUnread(): if message['read']: markMessageUnread(message['msgid']) + def clientStatus(): + """Print the client status""" + + global usrPrompt + try: - clientStatus = json.loads(api.clientStatus()) + client_status = json.loads(api.clientStatus()) except: print '\n Connection Error\n' usrPrompt = 0 main() - print "\nnetworkStatus: " + clientStatus['networkStatus'] + "\n" - print "\nnetworkConnections: " + str(clientStatus['networkConnections']) + "\n" - print "\nnumberOfPubkeysProcessed: " + str(clientStatus['numberOfPubkeysProcessed']) + "\n" - print "\nnumberOfMessagesProcessed: " + str(clientStatus['numberOfMessagesProcessed']) + "\n" - print "\nnumberOfBroadcastsProcessed: " + str(clientStatus['numberOfBroadcastsProcessed']) + "\n" + + print "\nnetworkStatus: " + client_status['networkStatus'] + "\n" + print "\nnetworkConnections: " + str(client_status['networkConnections']) + "\n" + print "\nnumberOfPubkeysProcessed: " + str(client_status['numberOfPubkeysProcessed']) + "\n" + print "\nnumberOfMessagesProcessed: " + str(client_status['numberOfMessagesProcessed']) + "\n" + print "\nnumberOfBroadcastsProcessed: " + str(client_status['numberOfBroadcastsProcessed']) + "\n" + def shutdown(): + """Shutdown the API""" + try: api.shutdown() except socket.error: @@ -1292,9 +1412,11 @@ def shutdown(): print "\nShutdown command relayed\n" -def UI(usrInput): #Main user menu +def UI(usrInput): + """Main user menu""" + global usrPrompt - + if usrInput == "help" or usrInput == "h" or usrInput == "?": print ' ' print ' -------------------------------------------------------------------------' @@ -1304,7 +1426,7 @@ def UI(usrInput): #Main user menu print ' |------------------------|----------------------------------------------|' print ' | help | This help file. |' print ' | apiTest | Tests the API |' - print ' | addInfo | Returns address information (If valid) |' + print ' | addInfo | Returns address information (If valid) |' print ' | bmSettings | BitMessage settings |' print ' | exit | Use anytime to return to main menu |' print ' | quit | Quits the program |' @@ -1319,7 +1441,6 @@ def UI(usrInput): #Main user menu print ' |------------------------|----------------------------------------------|' print ' | subscribe | Subscribes to an address |' print ' | unsubscribe | Unsubscribes from an address |' - #print' | listSubscriptions | Lists all of the subscriptions. |' print ' |------------------------|----------------------------------------------|' print ' | create | Creates a channel |' print ' | join | Joins a channel |' @@ -1336,8 +1457,8 @@ def UI(usrInput): #Main user menu print ' ' main() - elif usrInput == "apitest": #tests the API Connection. - if (apiTest() == True): + elif usrInput == "apitest": # tests the API Connection. + if apiTest(): print '\n API connection test has: PASSED\n' else: print '\n API connection test has: FAILED\n' @@ -1348,9 +1469,9 @@ def UI(usrInput): #Main user menu address_information = json.loads(api.decodeAddress(tmp_address)) print '\n------------------------------' - + if 'success' in str(address_information['status']).lower(): - print ' Valid Address' + print ' Valid Address' print ' Address Version: %s' % str(address_information['addressVersion']) print ' Stream Number: %s' % str(address_information['streamNumber']) else: @@ -1358,40 +1479,36 @@ def UI(usrInput): #Main user menu print '------------------------------\n' main() - - elif usrInput == "bmsettings": #tests the API Connection. + + elif usrInput == "bmsettings": # tests the API Connection. bmSettings() print ' ' main() - - elif usrInput == "quit": #Quits the application + + elif usrInput == "quit": # Quits the application print '\n Bye\n' - sys.exit() - os._exit() - - elif usrInput == "listaddresses": #Lists all of the identities in the addressbook + sys.exit(0) + + elif usrInput == "listaddresses": # Lists all of the identities in the addressbook listAdd() main() - - elif usrInput == "generateaddress": #Generates a new address + + elif usrInput == "generateaddress": # Generates a new address uInput = userInput('\nWould you like to create a (D)eterministic or (R)andom address?').lower() - if uInput in ["d", "deterministic"]: #Creates a deterministic address + if uInput in ["d", "deterministic"]: # Creates a deterministic address deterministic = True - #lbl = raw_input('Label the new address:') #currently not possible via the api lbl = '' - passphrase = userInput('Enter the Passphrase.')#.encode('base64') + passphrase = userInput('Enter the Passphrase.') # .encode('base64') numOfAdd = int(userInput('How many addresses would you like to generate?')) - #addVNum = int(raw_input('Address version number (default "0"):')) - #streamNum = int(raw_input('Stream number (default "0"):')) addVNum = 3 streamNum = 1 isRipe = userInput('Shorten the address, (Y)es or (N)o?').lower() if isRipe == "y": ripe = True - print genAdd(lbl,deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe) + print genAdd(lbl, deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe) main() elif isRipe == "n": ripe = False @@ -1404,40 +1521,37 @@ def UI(usrInput): #Main user menu print '\n Invalid input\n' main() - - elif uInput == "r" or uInput == "random": #Creates a random address with user-defined label + elif uInput == "r" or uInput == "random": # Creates a random address with user-defined label deterministic = False null = '' lbl = userInput('Enter the label for the new address.') - - print genAdd(lbl,deterministic, null,null, null, null, null) + + print genAdd(lbl, deterministic, null, null, null, null, null) main() - + else: print '\n Invalid input\n' main() - - elif usrInput == "getaddress": #Gets the address for/from a passphrase + + elif usrInput == "getaddress": # Gets the address for/from a passphrase phrase = userInput("Enter the address passphrase.") print '\n Working...\n' - #vNumber = int(raw_input("Enter the address version number:")) - #sNumber = int(raw_input("Enter the address stream number:")) - - address = getAddress(phrase,4,1)#,vNumber,sNumber) - print ('\n Address: ' + address + '\n') - + address = getAddress(phrase, 4, 1) # ,vNumber,sNumber) + print '\n Address: ' + address + '\n' usrPrompt = 1 main() - elif usrInput == "subscribe": #Subsribe to an address + elif usrInput == "subscribe": # Subsribe to an address subscribe() usrPrompt = 1 main() - elif usrInput == "unsubscribe": #Unsubscribe from an address + + elif usrInput == "unsubscribe": # Unsubscribe from an address unsubscribe() usrPrompt = 1 main() - elif usrInput == "listsubscriptions": #Unsubscribe from an address + + elif usrInput == "listsubscriptions": # Unsubscribe from an address listSubscriptions() usrPrompt = 1 main() @@ -1451,12 +1565,12 @@ def UI(usrInput): #Main user menu joinChan() usrPrompt = 1 main() - + elif usrInput == "leave": leaveChan() usrPrompt = 1 main() - + elif usrInput == "inbox": print '\n Loading...\n' inbox() @@ -1472,21 +1586,20 @@ def UI(usrInput): #Main user menu outbox() main() - elif usrInput == 'send': #Sends a message or broadcast + elif usrInput == 'send': # Sends a message or broadcast uInput = userInput('Would you like to send a (M)essage or (B)roadcast?').lower() if (uInput == 'm' or uInput == 'message'): null = '' - sendMsg(null,null,null,null) + sendMsg(null, null, null, null) main() - elif (uInput =='b' or uInput == 'broadcast'): + elif (uInput == 'b' or uInput == 'broadcast'): null = '' - sendBrd(null,null,null) + sendBrd(null, null, null) main() + elif usrInput == "read": # Opens a message from the inbox for viewing. - elif usrInput == "read": #Opens a message from the inbox for viewing. - uInput = userInput("Would you like to read a message from the (I)nbox or (O)utbox?").lower() if (uInput != 'i' and uInput != 'inbox' and uInput != 'o' and uInput != 'outbox'): @@ -1508,20 +1621,20 @@ def UI(usrInput): #Main user menu uInput = userInput("\nWould you like to (D)elete, (F)orward, (R)eply to, or (Exit) this message?").lower() - if (uInput == 'r' or uInput == 'reply'): + if uInput in ['r', 'reply']: print '\n Loading...\n' print ' ' - replyMsg(msgNum,'reply') - usrPrompt = 1 - - elif (uInput == 'f' or uInput == 'forward'): - print '\n Loading...\n' - print ' ' - replyMsg(msgNum,'forward') + replyMsg(msgNum, 'reply') usrPrompt = 1 - elif (uInput == "d" or uInput == 'delete'): - uInput = userInput("Are you sure, (Y)es or (N)o?").lower()#Prevent accidental deletion + elif uInput == 'f' or uInput == 'forward': + print '\n Loading...\n' + print ' ' + replyMsg(msgNum, 'forward') + usrPrompt = 1 + + elif uInput in ["d", 'delete']: + uInput = userInput("Are you sure, (Y)es or (N)o?").lower() # Prevent accidental deletion if uInput == "y": delMsg(msgNum) @@ -1532,14 +1645,15 @@ def UI(usrInput): #Main user menu else: print '\n Invalid entry\n' usrPrompt = 1 - + elif (uInput == 'o' or uInput == 'outbox'): readSentMsg(msgNum) - uInput = userInput("Would you like to (D)elete, or (Exit) this message?").lower() #Gives the user the option to delete the message + # Gives the user the option to delete the message + uInput = userInput("Would you like to (D)elete, or (Exit) this message?").lower() if (uInput == "d" or uInput == 'delete'): - uInput = userInput('Are you sure, (Y)es or (N)o?').lower() #Prevent accidental deletion + uInput = userInput('Are you sure, (Y)es or (N)o?').lower() # Prevent accidental deletion if uInput == "y": delSentMsg(msgNum) @@ -1550,111 +1664,116 @@ def UI(usrInput): #Main user menu else: print '\n Invalid Entry\n' usrPrompt = 1 - + main() - + elif usrInput == "save": - + uInput = userInput("Would you like to save a message from the (I)nbox or (O)utbox?").lower() - if (uInput != 'i' and uInput == 'inbox' and uInput != 'o' and uInput == 'outbox'): + if uInput not in ['i', 'inbox', 'o', 'outbox']: print '\n Invalid Input.\n' usrPrompt = 1 main() - if (uInput == 'i' or uInput == 'inbox'): + if uInput in ['i', 'inbox']: inboxMessages = json.loads(api.getAllInboxMessages()) numMessages = len(inboxMessages['inboxMessages']) while True: msgNum = int(userInput("What is the number of the message you wish to save?")) - if (msgNum >= numMessages): + if msgNum >= numMessages: print '\n Invalid Message Number.\n' else: break - - subject = inboxMessages['inboxMessages'][msgNum]['subject'].decode('base64') - message = inboxMessages['inboxMessages'][msgNum]['message']#Don't decode since it is done in the saveFile function - - elif (uInput == 'o' or uInput == 'outbox'): + + subject = inboxMessages['inboxMessages'][msgNum]['subject'].decode('base64') + # Don't decode since it is done in the saveFile function + message = inboxMessages['inboxMessages'][msgNum]['message'] + + elif uInput == 'o' or uInput == 'outbox': outboxMessages = json.loads(api.getAllSentMessages()) numMessages = len(outboxMessages['sentMessages']) while True: msgNum = int(userInput("What is the number of the message you wish to save?")) - if (msgNum >= numMessages): + if msgNum >= numMessages: print '\n Invalid Message Number.\n' else: break - - subject = outboxMessages['sentMessages'][msgNum]['subject'].decode('base64') - message = outboxMessages['sentMessages'][msgNum]['message']#Don't decode since it is done in the saveFile function - - subject = subject +'.txt' - saveFile(subject,message) - + + subject = outboxMessages['sentMessages'][msgNum]['subject'].decode('base64') + # Don't decode since it is done in the saveFile function + message = outboxMessages['sentMessages'][msgNum]['message'] + + subject = subject + '.txt' + saveFile(subject, message) + usrPrompt = 1 main() - - elif usrInput == "delete": #will delete a message from the system, not reflected on the UI. - + + elif usrInput == "delete": # will delete a message from the system, not reflected on the UI. + uInput = userInput("Would you like to delete a message from the (I)nbox or (O)utbox?").lower() - if (uInput == 'i' or uInput == 'inbox'): + if uInput in ['i', 'inbox']: inboxMessages = json.loads(api.getAllInboxMessages()) numMessages = len(inboxMessages['inboxMessages']) - - while True: - msgNum = userInput('Enter the number of the message you wish to delete or (A)ll to empty the inbox.').lower() - if (msgNum == 'a' or msgNum == 'all'): + while True: + msgNum = userInput( + 'Enter the number of the message you wish to delete or (A)ll to empty the inbox.').lower() + + if msgNum == 'a' or msgNum == 'all': break - elif (int(msgNum) >= numMessages): + elif int(msgNum) >= numMessages: print '\n Invalid Message Number.\n' else: break - - uInput = userInput("Are you sure, (Y)es or (N)o?").lower()#Prevent accidental deletion + + uInput = userInput("Are you sure, (Y)es or (N)o?").lower() # Prevent accidental deletion if uInput == "y": - if (msgNum == 'a' or msgNum == 'all'): + if msgNum in ['a', 'all']: print ' ' - for msgNum in range (0, numMessages): #processes all of the messages in the inbox - print ' Deleting message ', msgNum+1, ' of ', numMessages + for msgNum in range(0, numMessages): # processes all of the messages in the inbox + print ' Deleting message ', msgNum + 1, ' of ', numMessages delMsg(0) print '\n Inbox is empty.' usrPrompt = 1 else: delMsg(int(msgNum)) - + print '\n Notice: Message numbers may have changed.\n' main() else: usrPrompt = 1 - elif (uInput == 'o' or uInput == 'outbox'): + + elif uInput in ['o', 'outbox']: outboxMessages = json.loads(api.getAllSentMessages()) numMessages = len(outboxMessages['sentMessages']) - - while True: - msgNum = userInput('Enter the number of the message you wish to delete or (A)ll to empty the inbox.').lower() - if (msgNum == 'a' or msgNum == 'all'): + while True: + msgNum = userInput( + 'Enter the number of the message you wish to delete or (A)ll to empty the inbox.').lower() + + if msgNum in ['a', 'all']: break - elif (int(msgNum) >= numMessages): + elif int(msgNum) >= numMessages: print '\n Invalid Message Number.\n' else: break - uInput = userInput("Are you sure, (Y)es or (N)o?").lower()#Prevent accidental deletion + uInput = userInput("Are you sure, (Y)es or (N)o?").lower() # Prevent accidental deletion if uInput == "y": - if (msgNum == 'a' or msgNum == 'all'): + if msgNum in ['a', 'all']: print ' ' - for msgNum in range (0, numMessages): #processes all of the messages in the outbox - print ' Deleting message ', msgNum+1, ' of ', numMessages + for msgNum in range(0, numMessages): # processes all of the messages in the outbox + print ' Deleting message ', msgNum + 1, ' of ', numMessages delSentMsg(0) print '\n Outbox is empty.' @@ -1677,7 +1796,8 @@ def UI(usrInput): #Main user menu elif usrInput == "listaddressbookentries": res = listAddressBookEntries() - if res == 20: print '\n Error: API function not supported.\n' + if res == 20: + print '\n Error: API function not supported.\n' usrPrompt = 1 main() @@ -1685,15 +1805,18 @@ def UI(usrInput): #Main user menu address = userInput('Enter address') label = userInput('Enter label') res = addAddressToAddressBook(address, label) - if res == 16: print '\n Error: Address already exists in Address Book.\n' - if res == 20: print '\n Error: API function not supported.\n' + if res == 16: + print '\n Error: Address already exists in Address Book.\n' + if res == 20: + print '\n Error: API function not supported.\n' usrPrompt = 1 main() elif usrInput == "deleteaddressbookentry": address = userInput('Enter address') res = deleteAddressFromAddressBook(address) - if res == 20: print '\n Error: API function not supported.\n' + if res == 20: + print '\n Error: API function not supported.\n' usrPrompt = 1 main() @@ -1717,49 +1840,37 @@ def UI(usrInput): #Main user menu usrPrompt = 1 main() - elif usrInput == "million+": - genMilAddr() + else: + print '\n "', usrInput, '" is not a command.\n' usrPrompt = 1 main() - elif usrInput == "million-": - delMilAddr() - usrPrompt = 1 - main() - - else: - print '\n "',usrInput,'" is not a command.\n' - usrPrompt = 1 - main() - + def main(): + """Entrypoint for the CLI app""" + global api global usrPrompt - - if (usrPrompt == 0): + + if usrPrompt == 0: print '\n ------------------------------' print ' | Bitmessage Daemon by .dok |' print ' | Version 0.3.1 for BM 0.6.2 |' print ' ------------------------------' - api = xmlrpclib.ServerProxy(apiData()) #Connect to BitMessage using these api credentials + api = xmlrpclib.ServerProxy(apiData()) # Connect to BitMessage using these api credentials - if (apiTest() == False): + if apiTest() is False: print '\n ****************************************************************' print ' WARNING: You are not connected to the Bitmessage client.' print ' Either Bitmessage is not running or your settings are incorrect.' print ' Use the command "apiTest" or "bmSettings" to resolve this issue.' print ' ****************************************************************\n' - - print 'Type (H)elp for a list of commands.' #Startup message + + print 'Type (H)elp for a list of commands.' # Startup message usrPrompt = 2 - - #if (apiTest() == False):#Preform a connection test #taken out until I get the error handler working - # print '*************************************' - # print 'WARNING: No connection to Bitmessage.' - # print '*************************************' - # print ' ' - elif (usrPrompt == 1): - print '\nType (H)elp for a list of commands.' #Startup message + + elif usrPrompt == 1: + print '\nType (H)elp for a list of commands.' # Startup message usrPrompt = 2 try: @@ -1767,5 +1878,6 @@ def main(): except EOFError: UI("quit") + if __name__ == "__main__": - main() + main()