This repository has been archived on 2024-12-19. You can view files and clone it, but cannot push or open issues or pull requests.
PyBitmessage-2024-12-19/src/bmsettings.py
peter-tank 425eded1a2
Massive changes to src/bitmessagecli.py
* Mainly changes:
  * Message attachments faults detecting, and allow to dump whole embeded message alone to files.
  * Multi-line message acceptable in sending, (End with `Ctrl+D`)and allow resent on 'Connection Error.'
  * Print out detailed API Error returned.
  * Update Contacts list cmd, bcz contact list API returns unEncoded lable.
  * Message pull routing refine, mainlly access inbox messages by IDs, to reduce bandwidth usages.
  * API connections `SOCKS5` `HTTP` proxied.
* UIs
  * Shorten the user cmds inputs.
  * Try to remember user last choices.
  * Refine user input checkings.(rest to default selection by input a blank string)
  * A comprehensive command line parser, override configurations read from file `client.dat` in current working directory.
  * Message review limited to 380 characters in default.

default settings `client.dat`
```
[global]
start_daemon = http://127.0.0.1:8888
start_daemon = http://127.0.0.1:8445

[api]
path = 127.0.0.1:8445
type = HTTP

[proxy]
path = 127.0.0.1:1080
type = none
timeout = 30
remotedns = True
```

Signed-off-by: peter-tank <30540412+peter-tank@users.noreply.github.com>
2018-07-23 00:58:28 +08:00

374 lines
17 KiB
Python

#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
# 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
TODO: fix the following (currently ignored) violations:
"""
import sys
import os
from bmconfigparser import BMConfigParser
import ConfigParser
keysName = 'keys.dat'
keysPath = 'keys.dat'
def userInput(message):
"""Checks input for exit or quit. Also formats for input, etc"""
print message
uInput = raw_input('> ')
return uInput
def lookupAppdataFolder():
"""gets the appropriate folders for the .dat files depending on the OS. Taken from bitmessagemain.py"""
APPNAME = "PyBitmessage"
if sys.platform == 'darwin':
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.')
sys.exit(1)
elif 'win32' in sys.platform or 'win64' in sys.platform:
dataFolder = os.path.join(os.environ['APPDATA'], APPNAME) + '\\'
else:
dataFolder = os.path.expanduser(os.path.join("~", ".config/" + APPNAME + "/"))
return dataFolder
def configInit():
"""Initialised the configuration"""
BMConfigParser().add_section('bitmessagesettings')
# 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 ' {0} Initalized in the same directory as this CLI.\n' \
' You will now need to configure the {0} file.\n'.format(keysName)
def restartBmNotify():
"""Prompt the user to restart Bitmessage"""
print
print ' *******************************************************************'
print ' WARNING: If Bitmessage is running locally, you must restart it now.'
print ' *******************************************************************\n'
def apiInit(apiEnabled):
"""Initialise the API"""
global keysPath
BMConfigParser().read(keysPath)
isValid = False
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
with open(keysPath, 'wb') as configfile:
BMConfigParser().write(configfile)
print 'Done'
restartBmNotify()
isValid = True
elif uInput == "n":
print
print ' ************************************************************'
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'
else:
print '\n Invalid Entry\n'
elif apiEnabled: # API correctly setup
# Everything is as it should be
isValid = 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")
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'
# 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)
BMConfigParser().set('bitmessagesettings', 'apipassword', apiPwd)
BMConfigParser().set('bitmessagesettings', 'daemon', daemon)
with open(keysPath, 'wb') as configfile:
BMConfigParser().write(configfile)
print ' Finished configuring the keys.dat file with API information.\n'
restartBmNotify()
isValid = True
elif uInput == "n":
print
print ' ***********************************************************'
print ' Please refer to the Bitmessage Wiki on how to setup the API.'
print ' ***********************************************************\n'
else:
print ' \nInvalid entry\n'
return isValid
def apiData():
"""TBC"""
global keysName
global keysPath
print '\n Configure file searching:', os.path.realpath(keysPath)
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 (ConfigParser.NoSectionError, ConfigParser.NoOptionError) as err:
pass
# Could not load the keys.dat file in the program directory. Perhaps it is in the appdata directory.
appDataFolder = lookupAppdataFolder()
keysPath = appDataFolder + keysPath
print '\n Configure file searching:', os.path.realpath(keysPath)
BMConfigParser().read(keysPath)
try:
BMConfigParser().get('bitmessagesettings', 'port')
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) as err:
# keys.dat was not there either, something is wrong.
print
print ' *************************************************************'
print ' WARNING: There was a problem on accessing congfigure file.'
print ' Make sure that daemon is in the same directory as Bitmessage. '
print ' *************************************************************\n'
finalCheck = False
uInput = userInput('Would you like to create a "keys.dat" file in current working directory, (Y)es or (N)o?').lower()
if (uInput == "y" or uInput == "yes"):
configInit()
keysPath = keysName
f = True
elif (uInput == "n" or uInput == "no"):
print '\n Trying Again.\n'
else:
print '\n Invalid Input.\n'
if not finalCheck:
return ''
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 (ConfigParser.NoSectionError, ConfigParser.NoOptionError) as err:
isValid = apiInit("") # Initalize the keys.dat file with API information
if not isValid:
print '\n Config file not valid.\n'
return ''
# 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')
ret = "http://" + apiUsername + ":" + apiPassword + "@" + apiInterface + ":" + str(apiPort) + "/"
print '\n API data successfully imported.'
# Build the api credentials
return ret
def bmSettings():
"""Allows the viewing and modification of keys.dat settings."""
global keysPath
global usrPrompt
BMConfigParser().read(keysPath) # Read the keys.dat
try:
print ' Configure file loading:', os.path.realpath(keysPath)
port = BMConfigParser().get('bitmessagesettings', 'port')
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) as err:
print '\n File not found.\n'
return ''
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
print ' -----------------------------------'
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 ' ------------------------------------'
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, (n)o or (Y)es?').lower()
if uInput in ['y', 'yes']:
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("Input the new port number.")
BMConfigParser().set('bitmessagesettings', 'port', str(uInput))
elif uInput == "startonlogon":
print ' Current status: ' + str(startonlogon)
uInput = userInput("Input the new status.")
BMConfigParser().set('bitmessagesettings', 'startonlogon', str(uInput))
elif uInput == "minimizetotray":
print ' Current status: ' + str(minimizetotray)
uInput = userInput("Input the new status.")
BMConfigParser().set('bitmessagesettings', 'minimizetotray', str(uInput))
elif uInput == "showtraynotifications":
print ' Current status: ' + str(showtraynotifications)
uInput = userInput("Input the new status.")
BMConfigParser().set('bitmessagesettings', 'showtraynotifications', str(uInput))
elif uInput == "startintray":
print ' Current status: ' + str(startintray)
uInput = userInput("Input the new status.")
BMConfigParser().set('bitmessagesettings', 'startintray', str(uInput))
elif uInput == "defaultnoncetrialsperbyte":
print ' Current default nonce trials per byte: ' + defaultnoncetrialsperbyte
uInput = userInput("Input the new defaultnoncetrialsperbyte.")
BMConfigParser().set('bitmessagesettings', 'defaultnoncetrialsperbyte', str(uInput))
elif uInput == "defaultpayloadlengthextrabytes":
print ' Current default payload length extra bytes: ' + defaultpayloadlengthextrabytes
uInput = userInput("Input the new defaultpayloadlengthextrabytes.")
BMConfigParser().set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(uInput))
elif uInput == "daemon":
print ' Current status: ' + str(daemon)
uInput = userInput("Input 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("Input the new socksproxytype.")
BMConfigParser().set('bitmessagesettings', 'socksproxytype', str(uInput))
elif uInput == "sockshostname":
print ' Current socks host name: ' + sockshostname
uInput = userInput("Input the new sockshostname.")
BMConfigParser().set('bitmessagesettings', 'sockshostname', str(uInput))
elif uInput == "socksport":
print ' Current socks port number: ' + socksport
uInput = userInput("Input the new socksport.")
BMConfigParser().set('bitmessagesettings', 'socksport', str(uInput))
elif uInput == "socksauthentication":
print ' Current status: ' + str(socksauthentication)
uInput = userInput("Input the new status.")
BMConfigParser().set('bitmessagesettings', 'socksauthentication', str(uInput))
elif uInput == "socksusername":
print ' Current socks username: ' + socksusername
uInput = userInput("Input the new socksusername.")
BMConfigParser().set('bitmessagesettings', 'socksusername', str(uInput))
elif uInput == "sockspassword":
print ' Current socks password: ' + sockspassword
uInput = userInput("Input the new password.")
BMConfigParser().set('bitmessagesettings', 'sockspassword', str(uInput))
else:
print "\n Invalid field. Please try again.\n"
invalidInput = True
if invalidInput is not True: # don't prompt if they made a mistake.
uInput = userInput("Would you like to change another setting, (n)o or (Y)es?").lower()
if uInput in ['n', 'no']:
with open(keysPath, 'wb') as configfile:
src = BMConfigParser().write(configfile)
restartBmNotify()
break
def main():
apiData() # configuration file "keys.dat" searching
bmSettings()
if __name__ == "__main__":
main()