2016-07-16 17:42:19 +02:00
#!/usr/bin/python2.7
2015-01-19 18:53:07 +01:00
# 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
import time
import sys
import os
2016-12-06 10:47:39 +01:00
from configparser import BMConfigParser
2015-01-19 18:53:07 +01:00
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 '
def safeConfigGetBoolean ( section , field ) :
global keysPath
2016-12-06 10:47:39 +01:00
config = BMConfigParser ( )
2015-01-19 18:53:07 +01:00
config . read ( keysPath )
try :
return config . getboolean ( section , field )
except :
return False
#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 ( ) :
global keysName
2016-12-06 10:47:39 +01:00
config = BMConfigParser ( )
2015-01-19 18:53:07 +01:00
config . add_section ( ' bitmessagesettings ' )
config . 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.
config . set ( ' bitmessagesettings ' , ' apienabled ' , ' true ' ) #Sets apienabled to true in keys.dat
with open ( keysName , ' wb ' ) as configfile :
config . 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 keysPath
global usrPrompt
2016-12-06 10:47:39 +01:00
config = BMConfigParser ( )
2015-01-19 18:53:07 +01:00
config . 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 " : #
config . set ( ' bitmessagesettings ' , ' apienabled ' , ' true ' ) #Sets apienabled to true in keys.dat
with open ( keysPath , ' wb ' ) as configfile :
config . 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 '
config . 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.
config . set ( ' bitmessagesettings ' , ' apienabled ' , ' true ' )
config . set ( ' bitmessagesettings ' , ' apiport ' , apiPort )
config . set ( ' bitmessagesettings ' , ' apiinterface ' , ' 127.0.0.1 ' )
config . set ( ' bitmessagesettings ' , ' apiusername ' , apiUsr )
config . set ( ' bitmessagesettings ' , ' apipassword ' , apiPwd )
config . set ( ' bitmessagesettings ' , ' daemon ' , daemon )
with open ( keysPath , ' wb ' ) as configfile :
config . 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 ' \n Invalid entry \n '
usrPrompt = 1
main ( )
def apiData ( ) :
global keysName
global keysPath
global usrPrompt
2016-12-06 10:47:39 +01:00
config = BMConfigParser ( )
2015-01-19 18:53:07 +01:00
config . read ( keysPath ) #First try to load the config file (the keys.dat file) from the program directory
try :
config . 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
2016-12-06 10:47:39 +01:00
config = BMConfigParser ( )
2015-01-19 18:53:07 +01:00
config . read ( keysPath )
try :
config . 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
config . get ( ' bitmessagesettings ' , ' apiport ' )
config . get ( ' bitmessagesettings ' , ' apiinterface ' )
config . get ( ' bitmessagesettings ' , ' apiusername ' )
config . 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 ( safeConfigGetBoolean ( ' bitmessagesettings ' , ' apienabled ' ) ) #if false it will prompt the user, if true it will return true
config . read ( keysPath ) #read again since changes have been made
apiPort = int ( config . get ( ' bitmessagesettings ' , ' apiport ' ) )
apiInterface = config . get ( ' bitmessagesettings ' , ' apiinterface ' )
apiUsername = config . get ( ' bitmessagesettings ' , ' apiusername ' )
apiPassword = config . 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
2016-12-06 10:47:39 +01:00
config = BMConfigParser ( )
2015-01-19 18:53:07 +01:00
keysPath = ' keys.dat '
config . read ( keysPath ) #Read the keys.dat
try :
port = config . get ( ' bitmessagesettings ' , ' port ' )
except :
print ' \n File not found. \n '
usrPrompt = 0
main ( )
startonlogon = safeConfigGetBoolean ( ' bitmessagesettings ' , ' startonlogon ' )
minimizetotray = safeConfigGetBoolean ( ' bitmessagesettings ' , ' minimizetotray ' )
showtraynotifications = safeConfigGetBoolean ( ' bitmessagesettings ' , ' showtraynotifications ' )
startintray = safeConfigGetBoolean ( ' bitmessagesettings ' , ' startintray ' )
defaultnoncetrialsperbyte = config . get ( ' bitmessagesettings ' , ' defaultnoncetrialsperbyte ' )
defaultpayloadlengthextrabytes = config . get ( ' bitmessagesettings ' , ' defaultpayloadlengthextrabytes ' )
daemon = safeConfigGetBoolean ( ' bitmessagesettings ' , ' daemon ' )
socksproxytype = config . get ( ' bitmessagesettings ' , ' socksproxytype ' )
sockshostname = config . get ( ' bitmessagesettings ' , ' sockshostname ' )
socksport = config . get ( ' bitmessagesettings ' , ' socksport ' )
socksauthentication = safeConfigGetBoolean ( ' bitmessagesettings ' , ' socksauthentication ' )
socksusername = config . get ( ' bitmessagesettings ' , ' socksusername ' )
sockspassword = config . 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. " )
config . set ( ' bitmessagesettings ' , ' port ' , str ( uInput ) )
elif uInput == " startonlogon " :
print ' Current status: ' + str ( startonlogon )
uInput = userInput ( " Enter the new status. " )
config . set ( ' bitmessagesettings ' , ' startonlogon ' , str ( uInput ) )
elif uInput == " minimizetotray " :
print ' Current status: ' + str ( minimizetotray )
uInput = userInput ( " Enter the new status. " )
config . set ( ' bitmessagesettings ' , ' minimizetotray ' , str ( uInput ) )
elif uInput == " showtraynotifications " :
print ' Current status: ' + str ( showtraynotifications )
uInput = userInput ( " Enter the new status. " )
config . set ( ' bitmessagesettings ' , ' showtraynotifications ' , str ( uInput ) )
elif uInput == " startintray " :
print ' Current status: ' + str ( startintray )
uInput = userInput ( " Enter the new status. " )
config . set ( ' bitmessagesettings ' , ' startintray ' , str ( uInput ) )
elif uInput == " defaultnoncetrialsperbyte " :
print ' Current default nonce trials per byte: ' + defaultnoncetrialsperbyte
uInput = userInput ( " Enter the new defaultnoncetrialsperbyte. " )
config . set ( ' bitmessagesettings ' , ' defaultnoncetrialsperbyte ' , str ( uInput ) )
elif uInput == " defaultpayloadlengthextrabytes " :
print ' Current default payload length extra bytes: ' + defaultpayloadlengthextrabytes
uInput = userInput ( " Enter the new defaultpayloadlengthextrabytes. " )
config . set ( ' bitmessagesettings ' , ' defaultpayloadlengthextrabytes ' , str ( uInput ) )
elif uInput == " daemon " :
print ' Current status: ' + str ( daemon )
uInput = userInput ( " Enter the new status. " ) . lower ( )
config . 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. " )
config . set ( ' bitmessagesettings ' , ' socksproxytype ' , str ( uInput ) )
elif uInput == " sockshostname " :
print ' Current socks host name: ' + sockshostname
uInput = userInput ( " Enter the new sockshostname. " )
config . set ( ' bitmessagesettings ' , ' sockshostname ' , str ( uInput ) )
elif uInput == " socksport " :
print ' Current socks port number: ' + socksport
uInput = userInput ( " Enter the new socksport. " )
config . set ( ' bitmessagesettings ' , ' socksport ' , str ( uInput ) )
elif uInput == " socksauthentication " :
print ' Current status: ' + str ( socksauthentication )
uInput = userInput ( " Enter the new status. " )
config . set ( ' bitmessagesettings ' , ' socksauthentication ' , str ( uInput ) )
elif uInput == " socksusername " :
print ' Current socks username: ' + socksusername
uInput = userInput ( " Enter the new socksusername. " )
config . set ( ' bitmessagesettings ' , ' socksusername ' , str ( uInput ) )
elif uInput == " sockspassword " :
print ' Current socks password: ' + sockspassword
uInput = userInput ( " Enter the new password. " )
config . 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 :
config . 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 ' \n Label, 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 '
2015-06-20 09:54:15 +02:00
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 ( )
2015-01-19 18:53:07 +01:00
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 ( ' \n Please 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 ( " \n 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 . 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.
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
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 )
message = message [ : fnPos ] + ' ~<Attachment data removed for easier viewing>~ ' + 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 ' )
print ' Message: \n '
print message #inboxMessages['inboxMessages'][msgNum]['message'].decode('base64')
print ' '
def readMsg ( msgNum ) : #Opens a message for reading
global usrPrompt
try :
inboxMessages = json . loads ( api . getAllInboxMessages ( ) )
numMessages = len ( inboxMessages [ ' inboxMessages ' ] )
except :
print ' \n Connection Error \n '
usrPrompt = 0
main ( )
if ( msgNum > = numMessages ) :
print ' \n Invalid Message Number. \n '
main ( )
#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
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 ]
else :
fnPos = attPos
fileName = ' Attachment '