PyBitmessage/src/bitmessagecli.py

1773 lines
71 KiB
Python
Raw Normal View History

#!/usr/bin/python2.7
# 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.4.2, by .dok (Version 0.3.0)
import xmlrpclib
import datetime
import hashlib
import getopt
import imghdr
import ntpath
import json
2017-08-22 13:23:03 +02:00
import socket
import time
import sys
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
knownAddresses = dict()
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
usrPrompt = 1
main()
elif (uInput.lower() == 'quit'): #Quits the program
print '\n Bye\n'
sys.exit()
os.exit()
else:
return uInput
def restartBmNotify(): #Prompts 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
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) + '/'
else:
print ' Could not find home folder, please report this message and your OS X version to the Daemon Github.'
os.exit()
elif 'win32' in sys.platform or 'win64' in sys.platform:
dataFolder = path.join(environ['APPDATA'], APPNAME) + '\\'
else:
dataFolder = path.expanduser(path.join("~", ".config/" + APPNAME + "/"))
return dataFolder
def configInit():
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
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):
global usrPrompt
BMConfigParser().read(keysPath)
if (apiEnabled == 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
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. '
print ' Please refer to the Bitmessage Wiki on how to setup the API.'
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
return True
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
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()
if (daemon != 'true' and daemon != 'false'):
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')
BMConfigParser().set('bitmessagesettings', 'apiport', apiPort)
BMConfigParser().set('bitmessagesettings', 'apiinterface', '127.0.0.1')
BMConfigParser().set('bitmessagesettings', 'apiusername', apiUsr)
BMConfigParser().set('bitmessagesettings', 'apipassword', apiPwd)
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.'
print ' ***********************************************************\n'
usrPrompt = 1
main()
else:
print ' \nInvalid entry\n'
usrPrompt = 1
main()
def apiData():
global keysName
global keysPath
global usrPrompt
BMConfigParser().read(keysPath) #First try to load the config file (the keys.dat file) from the program directory
try:
BMConfigParser().get('bitmessagesettings','port')
appDataFolder = ''
except:
#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')
except:
#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'
print ' Make sure that daemon is in the same directory as Bitmessage. '
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
usrPrompt = 0
main()
elif (uInput == "n" or uInput == "no"):
print '\n Trying Again.\n'
usrPrompt = 0
main()
else:
print '\n Invalid Input.\n'
usrPrompt = 1
main()
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
#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
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
def apiTest(): #Tests the API connection to bitmessage. Returns true if it is connected.
try:
result = api.add(2,3)
except:
return False
if (result == 5):
return True
else:
return False
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
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')
startintray = BMConfigParser().safeGetBoolean('bitmessagesettings', 'startintray')
defaultnoncetrialsperbyte = BMConfigParser().get('bitmessagesettings', 'defaultnoncetrialsperbyte')
defaultpayloadlengthextrabytes = BMConfigParser().get('bitmessagesettings', 'defaultpayloadlengthextrabytes')
daemon = BMConfigParser().safeGetBoolean('bitmessagesettings', 'daemon')
socksproxytype = BMConfigParser().get('bitmessagesettings', 'socksproxytype')
sockshostname = BMConfigParser().get('bitmessagesettings', 'sockshostname')
socksport = BMConfigParser().get('bitmessagesettings', 'socksport')
socksauthentication = BMConfigParser().safeGetBoolean('bitmessagesettings', 'socksauthentication')
socksusername = BMConfigParser().get('bitmessagesettings', 'socksusername')
sockspassword = BMConfigParser().get('bitmessagesettings', 'sockspassword')
print '\n -----------------------------------'
print ' | Current Bitmessage Settings |'
print ' -----------------------------------'
print ' port = ' + port
print ' startonlogon = ' + str(startonlogon)
print ' minimizetotray = ' + str(minimizetotray)
print ' showtraynotifications = ' + str(showtraynotifications)
print ' startintray = ' + str(startintray)
print ' defaultnoncetrialsperbyte = ' + defaultnoncetrialsperbyte
print ' defaultpayloadlengthextrabytes = ' + defaultpayloadlengthextrabytes
print ' daemon = ' + str(daemon)
print '\n ------------------------------------'
print ' | Current Connection Settings |'
print ' -----------------------------------'
print ' socksproxytype = ' + socksproxytype
print ' sockshostname = ' + sockshostname
print ' socksport = ' + socksport
print ' socksauthentication = ' + str(socksauthentication)
print ' socksusername = ' + socksusername
print ' sockspassword = ' + sockspassword
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'
invalidInput = False
uInput = userInput("What setting would you like to modify?").lower()
print ' '
if uInput == "port":
print ' Current port number: ' + port
uInput = userInput("Enter the new port number.")
BMConfigParser().set('bitmessagesettings', 'port', str(uInput))
elif uInput == "startonlogon":
print ' Current status: ' + str(startonlogon)
uInput = userInput("Enter the new status.")
BMConfigParser().set('bitmessagesettings', 'startonlogon', str(uInput))
elif uInput == "minimizetotray":
print ' Current status: ' + str(minimizetotray)
uInput = userInput("Enter the new status.")
BMConfigParser().set('bitmessagesettings', 'minimizetotray', str(uInput))
elif uInput == "showtraynotifications":
print ' Current status: ' + str(showtraynotifications)
uInput = userInput("Enter the new status.")
BMConfigParser().set('bitmessagesettings', 'showtraynotifications', str(uInput))
elif uInput == "startintray":
print ' Current status: ' + str(startintray)
uInput = userInput("Enter the new status.")
BMConfigParser().set('bitmessagesettings', 'startintray', str(uInput))
elif uInput == "defaultnoncetrialsperbyte":
print ' Current default nonce trials per byte: ' + defaultnoncetrialsperbyte
uInput = userInput("Enter the new defaultnoncetrialsperbyte.")
BMConfigParser().set('bitmessagesettings', 'defaultnoncetrialsperbyte', str(uInput))
elif uInput == "defaultpayloadlengthextrabytes":
print ' Current default payload length extra bytes: ' + defaultpayloadlengthextrabytes
uInput = userInput("Enter the new defaultpayloadlengthextrabytes.")
BMConfigParser().set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(uInput))
elif uInput == "daemon":
print ' Current status: ' + str(daemon)
uInput = userInput("Enter the new status.").lower()
BMConfigParser().set('bitmessagesettings', 'daemon', str(uInput))
elif uInput == "socksproxytype":
print ' Current socks proxy type: ' + socksproxytype
print "Possibilities: 'none', 'SOCKS4a', 'SOCKS5'."
uInput = userInput("Enter the new socksproxytype.")
BMConfigParser().set('bitmessagesettings', 'socksproxytype', str(uInput))
elif uInput == "sockshostname":
print ' Current socks host name: ' + sockshostname
uInput = userInput("Enter the new sockshostname.")
BMConfigParser().set('bitmessagesettings', 'sockshostname', str(uInput))
elif uInput == "socksport":
print ' Current socks port number: ' + socksport
uInput = userInput("Enter the new socksport.")
BMConfigParser().set('bitmessagesettings', 'socksport', str(uInput))
elif uInput == "socksauthentication":
print ' Current status: ' + str(socksauthentication)
uInput = userInput("Enter the new status.")
BMConfigParser().set('bitmessagesettings', 'socksauthentication', str(uInput))
elif uInput == "socksusername":
print ' Current socks username: ' + socksusername
uInput = userInput("Enter the new socksusername.")
BMConfigParser().set('bitmessagesettings', 'socksusername', str(uInput))
elif uInput == "sockspassword":
print ' Current socks password: ' + sockspassword
uInput = userInput("Enter the new password.")
BMConfigParser().set('bitmessagesettings', 'sockspassword', str(uInput))
else:
print "\n Invalid input. Please try again.\n"
invalidInput = True
if invalidInput != 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":
print '\n Changes Made.\n'
with open(keysPath, 'wb') as configfile:
BMConfigParser().write(configfile)
restartBmNotify()
break
elif uInput == "n":
usrPrompt = 1
main()
else:
print "Invalid input."
usrPrompt = 1
main()
def validAddress(address):
address_information = api.decodeAddress(address)
address_information = eval(address_information)
if 'success' in str(address_information.get('status')).lower():
return True
else:
return False
def getAddress(passphrase,vNumber,sNumber):
passphrase = passphrase.encode('base64')#passphrase must be encoded
return api.getDeterministicAddress(passphrase,vNumber,sNumber)
def subscribe():
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):
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')
def unsubscribe():
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):
print '\n Invalid. "c" to cancel. Please try again.\n'
else:
break
uInput = userInput("Are you sure, (Y)es or (N)o?").lower()
api.deleteSubscription(address)
print ('\n You are now unsubscribed from: ' + address + '\n')
def listSubscriptions():
global usrPrompt
#jsonAddresses = json.loads(api.listSubscriptions())
#numAddresses = len(jsonAddresses['addresses']) #Number of addresses
print '\nLabel, Address, Enabled\n'
try:
print api.listSubscriptions()
except:
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():
global usrPrompt
password = userInput("Enter channel name")
password = password.encode('base64')
try:
print api.createChan(password)
except:
print '\n Connection Error\n'
usrPrompt = 0
main()
def joinChan():
global usrPrompt
while True:
address = userInput("Enter channel address")
if (address == "c"):
usrPrompt = 1
print ' '
main()
elif (validAddress(address)== 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)
except:
print '\n Connection Error\n'
usrPrompt = 0
main()
def leaveChan():
global usrPrompt
while True:
address = userInput("Enter channel address")
if (address == "c"):
usrPrompt = 1
print ' '
main()
elif (validAddress(address)== False):
print '\n Invalid. "c" to cancel. Please try again.\n'
else:
break
try:
print api.leaveChan(address)
except:
print '\n Connection Error\n'
usrPrompt = 0
main()
def listAdd(): #Lists all of the addresses and their info
global usrPrompt
try:
jsonAddresses = json.loads(api.listAddresses())
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 '\n --------------------------------------------------------------------------'
print ' | # | Label | Address |S#|Enabled|'
print ' |---|-------------------|-------------------------------------|--|-------|'
for addNum in range (0, numAddresses): #processes all of the addresses and lists them out
label = str(jsonAddresses['addresses'][addNum]['label'])
address = str(jsonAddresses['addresses'][addNum]['address'])
stream = str(jsonAddresses['addresses'][addNum]['stream'])
enabled = str(jsonAddresses['addresses'][addNum]['enabled'])
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'
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
addressLabel = lbl.encode('base64')
try:
generatedAddress = api.createRandomAddress(addressLabel)
except:
print '\n Connection Error\n'
usrPrompt = 0
main()
return generatedAddress
elif deterministic == True: #Generates a new deterministic address with the user inputs.
passphrase = passphrase.encode('base64')
try:
generatedAddress = api.createDeterministicAddresses(passphrase, numOfAdd, addVNum, streamNum, ripe)
except:
print '\n Connection Error\n'
usrPrompt = 0
main()
return generatedAddress
else:
return 'Entry Error'
def delMilAddr(): #Generate 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()
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:
generatedAddress = api.createRandomAddress(addressLabel)
except:
print '\n Connection Error\n'
usrPrompt = 0
main()
def saveFile(fileName, fileData): #Allows attachments and messages/broadcats to be saved
#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(":", "~")
fileName = fileName.replace("*", "~")
fileName = fileName.replace("?", "~")
fileName = fileName.replace('"', "~")
fileName = fileName.replace("<", "~")
fileName = fileName.replace(">", "~")
fileName = fileName.replace("|", "~")
directory = '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'''
f = open(filePath, 'wb+') #Begin saving to file
f.write(fileData.decode("base64"))
f.close
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.')
try:
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?)
invSize = os.path.getsize(filePath)
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'
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.
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
if filetype is not None:
print '\n ---------------------------------------------------'
print ' Attachment detected as an Image.'
print ' <img> tags will automatically be included,'
print ' allowing the recipient to view the image'
print ' using the "View HTML code..." option in Bitmessage.'
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.
data = data.encode("base64")
if (isImage == True): #If it is an image, include image tags in the message
theAttachment = """
<!-- Note: Image attachment below. Please use the right click "View HTML code ..." option to view it. -->
<!-- Sent using Bitmessage Daemon. https://github.com/Dokument/PyBitmessage-Daemon -->
Filename:%s
Filesize:%sKB
Encoding:base64
<center>
<div id="image">
<img alt = "%s" src='data:image/%s;base64, %s' />
</div>
</center>""" % (fileName,invSize,fileName,filetype,data)
else: #Else it is not an image so do not include the embedded image code.
theAttachment = """
<!-- Note: File attachment below. Please use a base64 decoder, or Daemon, to save it. -->
<!-- Sent using Bitmessage Daemon. https://github.com/Dokument/PyBitmessage-Daemon -->
Filename:%s
Filesize:%sKB
Encoding:base64
<attachment alt = "%s" src='data:file/%s;base64, %s' />""" % (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'):
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.
global usrPrompt
if (validAddress(toAddress)== False):
while True:
toAddress = userInput("What is the To Address?")
if (toAddress == "c"):
usrPrompt = 1
print ' '
main()
elif (validAddress(toAddress)== False):
print '\n Invalid Address. "c" to cancel. Please try again.\n'
else:
break
if (validAddress(fromAddress)== False):
try:
jsonAddresses = json.loads(api.listAddresses())
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
found = False
while True:
print ' '
fromAddress = userInput("Enter an Address or Address Label to send from.")
if fromAddress == "exit":
usrPrompt = 1
main()
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
fromAddress = address
found = True
break
if (found == False):
if(validAddress(fromAddress)== 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']
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.
found = True
break
if (found == 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
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.")
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'
except:
print '\n Connection Error\n'
usrPrompt = 0
main()
def sendBrd(fromAddress, subject, message): #sends a broadcast
global usrPrompt
if (fromAddress == ''):
try:
jsonAddresses = json.loads(api.listAddresses())
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
found = False
while True:
fromAddress = userInput("\nEnter an Address or Address Label to send from.")
if fromAddress == "exit":
usrPrompt = 1
main()
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
fromAddress = address
found = True
break
if (found == False):
if(validAddress(fromAddress)== 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']
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.
found = True
break
if (found == 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
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.")
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)
print '\n Message Status:', api.getStatus(ackData), '\n'
except:
print '\n Connection Error\n'
usrPrompt = 0
main()
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())
numMessages = len(inboxMessages['inboxMessages'])
except:
print '\n Connection Error\n'
usrPrompt = 0
main()
messagesPrinted = 0
messagesUnread = 0
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')
messagesPrinted += 1
if not message['read']: messagesUnread += 1
if (messagesPrinted%20 == 0 and messagesPrinted != 0):
uInput = userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower()
print '\n -----------------------------------'
print ' There are %d unread messages of %d messages in the inbox.' % (messagesUnread, numMessages)
print ' -----------------------------------\n'
def outbox():
global usrPrompt
try:
outboxMessages = json.loads(api.getAllSentMessages())
numMessages = len(outboxMessages['sentMessages'])
except:
print '\n Connection Error\n'
usrPrompt = 0
main()
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')
if (msgNum%20 == 0 and msgNum != 0):
uInput = userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower()
print '\n -----------------------------------'
print ' There are ',numMessages,' messages in the outbox.'
print ' -----------------------------------\n'
def readSentMsg(msgNum): #Opens a sent message for reading
global usrPrompt
try:
outboxMessages = json.loads(api.getAllSentMessages())
numMessages = len(outboxMessages['sentMessages'])
except:
print '\n Connection Error\n'
usrPrompt = 0
main()
print ' '
if (msgNum >= numMessages):
print '\n Invalid Message Number.\n'
main()
#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.