-
-
Save anonymous/129d926d08380fceebe35ee24182ee40 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python2 | |
# -*- coding: utf-8 -*- | |
''' | |
o x e x o r h a s h e x o (bitmessage) BM-NBfVnT48vSeyjQ9bceneRuW76NypwRsx | |
r r (email) xor@danwin1210.me | |
h ┏┓┏┓┏━━┓┏━┓ h | |
a ┗╋╋┛┃┏┓┃┃┏┛ a Copyright (c) 2017 by Exor Hash Comsec Trust. | |
s ┏╋╋┓┃┗┛┃┃┃ s All rights reserved. | |
h ┗┛┗┛┗━━┛┗┛ h | |
s s This software and accompaniments are subject to the | |
a exor hash a terms of the SSS License v0.0, included herewith. | |
h comsec h | |
r r | |
o x e x o r h a s h e x o | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
See:Sue:Sell (SSS) license version 0.0 | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
You may see this code. There is no warranty. You agree you shall not sue me. You | |
agree that no claim of damages may arise from use of this software. You may not | |
sell this software. You agree you have no rights incidental to use of this code. | |
Rights not granted by this license are reserved to the author. | |
''' | |
# STATBOT v0.0 : pings other STATBOTS to measure bitmessage transit times | |
''' HELLO! READ THESE COMMENTS ON HOW TO INSTALL! ''' | |
# First shut down bitmessage. Don't try to install with bitmessage running. | |
# Copy the file 'statbot.py' to the same directory as bitmessagemain.py | |
# Navigate to the same directory with a terminal. | |
# In terminal type 'python2 statbot.py setup'. (without the quotes) | |
# The statbot installation wizard will guide the installation. | |
# After that, start up bitmessage, then run the script from the command line: | |
# $ python2 statbot.py run | |
# End of comments and header. | |
# ------------------------------------------------------------------------------ | |
import sys | |
if len(sys.argv) > 2: | |
print "bad command line argument. try 'statbot.py help'." | |
sys.exit() | |
if len(sys.argv) < 2: | |
print "( statbot ) ( error ) You must specify a statbot switch after the command." | |
print "( statbot ) switches: 'help', 'run', 'ping', 'bonk', 'logo', 'info', 'setup'." | |
print "( statbot ) examples: 'statbot.py run', 'statbot.py logo', 'statbot.py bonk'." | |
sys.exit() | |
if len(sys.argv) == 2 and sys.argv[1] == "help": | |
print "( statbot ) ( help ) valid switches: 'help', 'run', 'ping', 'bonk', 'logo', 'info', 'setup'." | |
print "( statbot ) ( help ) example: 'statbot.py run', 'statbot.py logo', 'statbot.py bonk'." | |
sys.exit() | |
if len(sys.argv) == 2 and sys.argv[1] == "logo": | |
logo = ''' | |
o x e x o r h a s h e x o (bitmessage) BM-NBfVnT48vSeyjQ9bceneRuW76NypwRsx | |
r r (email) xor@danwin1210.me | |
h ┏┓┏┓┏━━┓┏━┓ h | |
a ┗╋╋┛┃┏┓┃┃┏┛ a Copyright (c) 2017 by Exor Hash Comsec Trust. | |
s ┏╋╋┓┃┗┛┃┃┃ s All rights reserved. | |
h ┗┛┗┛┗━━┛┗┛ h | |
s s This software and accompaniments are subject to the | |
a exor hash a terms of the SSS License v0.0, included herewith. | |
h comsec h | |
r r | |
o x e x o r h a s h e x o | |
''' | |
print logo | |
sys.exit() | |
if len(sys.argv) == 2 and sys.argv[1] == "info": | |
info = ''' | |
STATBOT : pings other STATBOTS to measure bitmessage transit times. | |
The statbot periodically sends a bitmessage to a chan that is monitored by all | |
other statbots. They gather and share timestamp data to estimate metrics on how | |
long it takes a bitmessage to traverse the network in usage (not just transit), | |
including PoW time. Since PoW time is neglibible for short messages this is a | |
good estimation of either traversal from send or transit between sockets. | |
Follow the setup instructions, then once set up with bitmessage running, open a | |
terminal and type the command 'statbot.py run' to start the pinger. Over a | |
period of many hours (or days) the timestamps will be analyzed and a periodic | |
report will be sent by every statbot at random intervals. You must run the | |
pinger for statbot to gather proper statistics. | |
Every ping that is sent is automatically handled by the bitmessage api as soon | |
as each ping message arrives. Once running zero interaction is required. | |
The extra commands 'ping' and 'bonk' are included for troubleshooting and should | |
not be invoked in normal usage. | |
''' | |
print info | |
sys.exit() | |
from bmconfigparser import BMConfigParser | |
import ConfigParser | |
import subprocess | |
import xmlrpclib | |
import ntpath | |
import socket | |
import base64 | |
import random | |
import json | |
import time | |
import api | |
import sys | |
import os | |
app_dir = os.path.dirname(os.path.abspath(__file__)) | |
os.chdir(app_dir) | |
print "( statbot ) ( app dir ) ", app_dir | |
print "( statbot ) ( file ) ", __file__ | |
if not os.path.isfile("bitmessagemain.py"): | |
print "( statbot ) [ ERROR 02 ] could not find 'bitmessagemain.py.'" | |
print "( statbot ) statbot.py must be placed in bitmessage /src/ directory to run." | |
print "( statbot ) [ ERROR 02 ] cannot proceed. exiting." | |
sys.exit | |
statbotpath = os.path.abspath(__file__) | |
if not os.path.exists("statbot"): | |
os.makedirs("statbot") | |
def wait(secs): | |
time.sleep(secs) | |
def loput(iput, match): | |
if iput.lower() == match.lower(): | |
return True | |
else: | |
return False | |
def getApiPort(): | |
tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
tcp.bind(('', 0)) | |
addr, port = tcp.getsockname() | |
tcp.close() | |
return port | |
def getApiAddress(): | |
tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
tcp.bind(('', 0)) | |
host, port = tcp.getsockname() | |
tcp.close() | |
#return 'tcp://{host}:{port}'.format(**locals()) | |
return host | |
def drawHeader(): | |
try: | |
os.system('cls' if os.name == 'nt' else 'clear') | |
except: | |
print '' | |
try: | |
os.system('cls' if os.name == 'nt' else 'tput reset') | |
except: | |
print '' | |
print '' | |
print ' STATBOT v0.0' | |
print '________________________________________________________________________________' | |
print '' | |
def findKeysFolder(): # Ref. { PyBitmessage/bminterface.py } | |
import sys | |
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: | |
drawHeader() | |
print '( statbot ) [ ERROR ] ( install ) OS X: Unable to find keys directory.' | |
print '( statbot ) [ ERROR ] ( install ) Try to configure keys.dat manually.' | |
print '( statbot ) [ ERROR ] ( install ) STATBOT may not run on your system. exiting.' | |
sys.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 getApiString(): | |
global keysPath | |
config = ConfigParser.SafeConfigParser() | |
keysPath = 'keys.dat' | |
config.read(keysPath) # first try to load keys.dat from source directory. | |
try: | |
config.get('bitmessagesettings','settingsversion') | |
keysFolder = '' | |
except: | |
# keys.dat not found in source directory. Try appdata directory. | |
keysFolder = findKeysFolder() | |
keysPath = keysFolder + 'keys.dat' | |
config = ConfigParser.SafeConfigParser() | |
config.read(keysPath) | |
try: | |
config.get('bitmessagesettings','settingsversion') | |
except: | |
# keys.dat not there either. something is wrong. | |
drawHeader() | |
print ' ' | |
print '+--------------------------------------------------------------------+' | |
print '| STATBOT is unable to access the Bitmessage keys.dat file. |' | |
print '| Check to ensure statbot is in the same directory as Bitmessage. |' | |
print '+--------------------------------------------------------------------+' | |
print ' ' | |
print config | |
print ' ' | |
try: | |
apiPort = config.getint('bitmessagesettings', 'apiport') | |
except: | |
print '( statbot ) ( error ) unable to access keys.dat' | |
try: | |
apiInterface = config.get('bitmessagesettings', 'apiinterface') | |
except: | |
print '( statbot ) ( error ) unable to access keys.dat' | |
try: | |
apiUsername = config.get('bitmessagesettings', 'apiusername') | |
except: | |
print '( statbot ) ( error ) unable to access keys.dat' | |
try: | |
apiPassword = config.get('bitmessagesettings', 'apipassword') | |
except: | |
print '( statbot ) ( error ) unable to access keys.dat' | |
apiString = "http://" + apiUsername + ":" + apiPassword + "@" + apiInterface+ ":" + str(apiPort) + "/" | |
return apiString | |
api_string = getApiString() | |
# being install wizard | |
def apiData(): | |
global keysPath | |
config = ConfigParser.SafeConfigParser() | |
keysPath = 'keys.dat' | |
config.read(keysPath) # first try to load keys.dat from source directory. | |
try: | |
config.get('bitmessagesettings','settingsversion') | |
keysFolder = '' | |
except: | |
# keys.dat not found in source directory. Try appdata directory. | |
keysFolder = findKeysFolder() | |
keysPath = keysFolder + 'keys.dat' | |
config = ConfigParser.SafeConfigParser() | |
config.read(keysPath) | |
try: | |
config.get('bitmessagesettings','settingsversion') | |
except: | |
# keys.dat not there either. something is wrong. | |
drawHeader() | |
print ' ' | |
print '+--------------------------------------------------------------------+' | |
print '| STATBOT is unable to access the Bitmessage keys.dat file. |' | |
print '| Check to ensure statbot is in the same directory as Bitmessage. |' | |
print '+--------------------------------------------------------------------+' | |
print ' ' | |
print config | |
print ' ' | |
try: | |
apiConfigured = config.getboolean('bitmessagesettings','apienabled') | |
apiEnabled = apiConfigured | |
except: | |
apiConfigured = False # if not found set to false to force configuration. | |
print "API is disabled. STATBOT must enable and configure the Bitmessage API." | |
print "Use the 'setup' command to do this automatically." | |
raise | |
try: | |
notifypathtrue = config.has_option('bitmessagesettings', 'apinotifypath') | |
notifypath = config.get('bitmessagesettings', 'apinotifypath') | |
except: | |
notifypath = " (!) apinotifypath not configured for statbot." | |
# keys.dat found. retrieve data. | |
# if any setting is null, false, or incorrect, increment a boolean match, to ensure setup runs. | |
misconfigured = False | |
try: | |
apiEnabled = config.getboolean('bitmessagesettings','apienabled') | |
except: | |
apiEnabled = False | |
if apiEnabled != True: | |
misconfigured = True | |
apiEnabled = str(apiEnabled) + " (!)" | |
try: | |
apiPort = config.getint('bitmessagesettings', 'apiport') | |
except: | |
misconfigured = True | |
apiPort = " (!)" | |
try: | |
apiInterface = config.get('bitmessagesettings', 'apiinterface') | |
except: | |
misconfigured = True | |
apiInterface += " (!)" | |
if "." not in apiInterface: | |
misconfigured = True | |
apiInterface += " (!)" | |
try: | |
apiUsername = config.get('bitmessagesettings', 'apiusername') | |
except: | |
misconfigured = True | |
apiUsername += " (!)" | |
try: | |
apiPassword = config.get('bitmessagesettings', 'apipassword') | |
except: | |
misconfigured = True | |
apiPassword += " (!)" | |
try: | |
apinotifypath = config.get('bitmessagesettings', 'apinotifypath') | |
except: | |
misconfigured = True | |
apinotifypath = " (!)" | |
if apinotifypath != statbotpath and apinotifypath != "": | |
apinotifypath += " (!)" | |
misconfigured = True | |
if apinotifypath == "": | |
apinotifypath += " (!)" | |
misconfigured = True | |
drawHeader() | |
print ' +---------------------------------+' | |
print ' | Current STATBOT API Settings | (!) Indicates a bad setting.' | |
print ' +---------------------------------+' | |
print '' | |
print ' statbotpath = ' + str(statbotpath) | |
print ' apinotifypath = ' + str(apinotifypath) | |
print ' apiEnabled = ' + str(apiEnabled) | |
print ' apiPort = ' + str(apiPort) | |
print ' apiInterface = ' + str(apiInterface) | |
print ' apiUsername = ' + str(apiUsername) | |
print ' apiPassword = ' + str(apiPassword) | |
print '' | |
print '' | |
if notifypath != statbotpath or misconfigured == True: | |
print ' STATBOT must permanently change these settings to install and run.' | |
print ' Would you like STATBOT to do this automatically (Y)es / (N)o ?' | |
print '' | |
valid = False | |
userInput = raw_input(' [$] ') | |
print '\n ( statbot ) ( setup ) ' + str(userInput) | |
if userInput.lower() == "yes": | |
setupWizard(statbotpath, apinotifypath, apiEnabled, apiPort, apiInterface, apiUsername, apiPassword) | |
valid = True | |
elif userInput.lower() == "y": | |
setupWizard(statbotpath, apinotifypath, apiEnabled, apiPort, apiInterface, apiUsername, apiPassword) | |
valid = True | |
elif userInput.lower() == "no" or userInput.lower() == "n": | |
print " (!) returning to command help menu." | |
wait(1.5) | |
installMenu() | |
valid = True | |
elif valid == False and "yes" not in userInput.lower() and "no" not in userInput.lower(): | |
print "( " + userInput + " ) is an invalid command." | |
print " (!) returning to command help menu." | |
wait(1.5) | |
installMenu() | |
if notifypath == statbotpath and misconfigured == False: | |
print ' STATBOT and bitmessage settings appear correct.' | |
print ' Would you like STATBOT to reconfigure anyway? (Y)es / (N)o ?' | |
print '' | |
valid = False | |
userInput = raw_input(' [$] ') | |
print '\n ( statbot ) ( setup ) ' + str(userInput) | |
if userInput.lower() == "yes": | |
setupWizard(statbotpath, apinotifypath, apiEnabled, apiPort, apiInterface, apiUsername, apiPassword) | |
valid = True | |
elif userInput.lower() == "y": | |
setupWizard(statbotpath, apinotifypath, apiEnabled, apiPort, apiInterface, apiUsername, apiPassword) | |
valid = True | |
elif userInput.lower() == "no" or userInput.lower() == "n": | |
print " (!) returning to command help menu." | |
wait(1.5) | |
installMenu() | |
valid = True | |
elif valid == False and "yes" not in userInput.lower() and "no" not in userInput.lower(): | |
print "( " + userInput + " ) is an invalid command." | |
print " (!) returning to command help menu." | |
wait(1.5) | |
installMenu() | |
def show_api(): | |
drawHeader() | |
print '\n\n\n current Bitmessage API connection string:\n\n ' + api_string + "\n\n\n" | |
userInput = raw_input(' [$] press <enter> to go back to menu. [$]') | |
installMenu() | |
def installMenu(): | |
drawHeader() | |
print ' +----------------------------------------------------------+' | |
print ' | Available Commands |' | |
print ' +----------------------------------------------------------+' | |
print ' | |' | |
print ' | help : show this help guide. |' | |
print ' | quit : quit the program. |' | |
print ' | test : test the bitmessage / statbot API link. |' | |
print ' | show : show the API connection string. |' | |
print ' | setup : setup bitmessage to run statbot. |' | |
print ' | |' | |
print ' +----------------------------------------------------------+' | |
print '' | |
userInput = raw_input(' [$] ') | |
userInput = userInput.lower() | |
if userInput == "help" or userInput == "h" or userInput == "?": | |
installMenu() | |
elif userInput == "setup": | |
apiData() | |
elif userInput == "test": | |
apiData() | |
elif userInput == "show": | |
show_api() | |
elif userInput == "quit" or userInput == "exit": | |
print ' ( statbot ) ( exit )' | |
sys.exit() | |
else: | |
print " not a valid command. try again." | |
wait(2) | |
installMenu() | |
def changeSettings(apinotifypath, apiEnabled, apiPort, apiInterface, apiUsername, apiPassword): | |
global keysPath | |
# avoid using BMConfigParser, as it requires redrawing every entry in the file. | |
''' | |
BMConfigParser().add_section('bitmessagesettings') | |
BMConfigParser().set('bitmessagesettings', 'statbot', 'true') | |
BMConfigParser().set('bitmessagesettings', 'statbotversion', '0.0') | |
BMConfigParser().set('bitmessagesettings', 'apienabled','true') | |
BMConfigParser().set('bitmessagesettings', 'apinotifypath', str(apinotifypath)) | |
BMConfigParser().set('bitmessagesettings', 'apienabled', str(apiEnabled)) | |
BMConfigParser().set('bitmessagesettings', 'apiport', str(apiPort)) | |
BMConfigParser().set('bitmessagesettings', 'apiinterface', str(apiInterface)) | |
BMConfigParser().set('bitmessagesettings', 'apiusername', str(apiUsername)) | |
BMConfigParser().set('bitmessagesettings', 'apipassword', str(apiPassword)) | |
''' | |
try: | |
with open(keysPath, 'a') as configfile: | |
configfile.write("\n\n\n") | |
configfile.write("\n[bitmessagesettings]") | |
configfile.write("\nstatbot = True") | |
configfile.write("\nstatbotversion = 0.0") | |
configfile.write("\napienabled = True") | |
configfile.write("\napinotifypath = " + str(apinotifypath)) | |
configfile.write("\napiport = " + str(apiPort)) | |
configfile.write("\napiinterface = " + str(apiInterface)) | |
configfile.write("\napiusername = " + apiUsername) | |
configfile.write("\napipassword = " + apiPassword) | |
configfile.write("\n\n\n") | |
#BMConfigParser().write(configfile) | |
configfile.close() | |
except: | |
print " (!) Unknown error. terminating program." | |
wait(1.5) | |
raise | |
sys.exit() | |
print '' | |
print " success! changes written to keys.dat." | |
print " shut down and restart bitmessage for changes to take effect." | |
print "" | |
print " (!) all done. exiting." | |
wait(1.5) | |
sys.exit() | |
def randomToken(): | |
from base64 import b64encode | |
from os import urandom | |
random_bytes = urandom(64) | |
token = b64encode(random_bytes).decode('utf-8') | |
token = token.replace("/", "") | |
token = token.replace("+", "") | |
token = token[19:39] | |
return token | |
def setupWizard(statbotpath, apinotifypath, apiEnabled, apiPort, apiInterface, apiUsername, apiPassword): | |
# generate new settings values | |
apinotifypath = statbotpath | |
apiEnabled = True | |
apiPort = getApiPort() | |
apiInterface = getApiAddress() | |
apiUsername = randomToken() | |
apiPassword = randomToken() | |
valid = False | |
while valid == False: | |
sys.stdout.write("\r") | |
sys.stdout.flush() | |
drawHeader() | |
print ' +---------------------------------+' | |
print ' | Automatic Setup Wizard |' | |
print ' +---------------------------------+' | |
print '' | |
print ' Review of proposed settings:' | |
print '' | |
print ' apinotifypath = ' + str(statbotpath) | |
print ' apiEnabled = True' | |
print ' apiPort = ' + str(apiPort) | |
print ' apiInterface = ' + str(apiInterface) | |
print ' apiUsername = ' + str(apiUsername) | |
print ' apiPassword = ' + str(apiPassword) | |
print '' | |
print " To apply changes, type 'yes' and press 'enter'." | |
print " To cancel type 'no' and press 'enter'. (yes), (no) ?" | |
userInput = raw_input(' [$] ') | |
userInput = userInput.lower() | |
if userInput == "no": | |
installMenu() | |
valid == True | |
yes = loput(userInput, "yes") | |
if yes: | |
changeSettings(apinotifypath, apiEnabled, apiPort, apiInterface, apiUsername, apiPassword) | |
valid == True | |
if userInput != "yes" and userInput != "no": | |
print " (!) Invalid command. ( ", str(userInput), " ) Try again." | |
valid == False | |
wait(1.5) | |
if len(sys.argv) == 2 and sys.argv[1] == "setup": | |
installMenu() # show the setup commands menu | |
sys.exit() | |
# end install wizard | |
# begin the statbot | |
print "( statbot ) ( app dir ) ", app_dir | |
print "( statbot ) ( file ) ", __file__ | |
api = xmlrpclib.ServerProxy(api_string) | |
print "( statbot ) ( api_string ) ", api_string | |
#command = sys.argv[0] #will use later, for now __file__ | |
def apiTest(): | |
try: | |
result = api.add(4,5) | |
if result == 9: | |
print "( statbot ) bitmessage API is enabled and responding. proceeding." | |
elif result != 9: | |
print "( statbot ) bitmessage API error. check keys.dat configuration." | |
print "( statbot ) bitmessage API error. is bitmessage running?. exiting." | |
sys.exit() | |
except: | |
print "( statbot ) bitmessage API error. check keys.dat configuration. is API enabled?" | |
print "( statbot ) bitmessage API error. is bitmessage running?. exiting." | |
sys.exit() | |
# create the statbot chan for message pool (all STATBOTS use same chan) | |
def checkChan(chanName): | |
try: | |
passphrase = chanName.encode('base64') | |
checkphrase = api.createChan(passphrase) | |
api.statusBar("( statbot ) checking chan.") | |
except ValueError: | |
print "( statbot ) [ ERROR 00 ] unable to create channel." | |
print "( statbot ) [ ERROR 00 ] if channel exists this is not an error. continuing." | |
api.statusBar("( statbot ) checking chan.") | |
return checkphrase | |
chanName = "stat_bonk" | |
checkphrase = checkChan(chanName) | |
api.statusBar("( statbot ) checking chan.") | |
if "Chan address is already present" in checkphrase: | |
print "( statbot ) success. [chan] " + chanName + " exists. proceeding." | |
elif checkphrase[:3] == "BM-": | |
print "( statbot ) success. [chan] " + chanName + " created. proceeding." | |
elif checkphrase != "": | |
print "( statbot ) [ ERROR 01 ] [ BM-API ] error creating [chan] ", checkphrase, "exiting." | |
api.statusBar("( statbot ) [ ERROR 01 ] exiting.") | |
sys.exit() | |
chanName = "stat_ping" | |
checkphrase = checkChan(chanName) | |
api.statusBar("( statbot ) checking chan.") | |
if "Chan address is already present" in checkphrase: | |
print "( statbot ) success. [chan] " + chanName + " exists. proceeding." | |
elif checkphrase[:3] == "BM-": | |
print "( statbot ) success. [chan] " + chanName + " created. proceeding." | |
elif checkphrase != "": | |
print "( statbot ) [ ERROR 01 ] [ BM-API ] error creating [chan] ", checkphrase, "exiting." | |
api.statusBar("( statbot ) [ ERROR 01 ] exiting.") | |
sys.exit() | |
def getAddress(passphrase,vNumber,sNumber): | |
passphrase = passphrase.encode('base64') | |
return api.getDeterministicAddress(passphrase,vNumber,sNumber) | |
api.statusBar("( statbot ) getting chan address.") | |
# check for statbot ID file. if non-existent, generate a new botID and add to file. | |
# if it exists, read the botID to variable | |
def getBotID(): | |
if not os.path.isfile("statbot/bmstatbotID.dat"): | |
try: | |
lo = 100000000000000000000000 | |
hi = 999999999999999999999999 | |
botNum = random.randrange(lo, hi) | |
botID = str(hex(botNum)).strip("L")[2:18] | |
print "( statbot ) [ BOTID ] generated new botID: ", botID | |
readID = open("statbot/bmstatbotID.dat", "w") | |
botID = readID.write(botID) | |
readID.close() | |
return botID | |
except: | |
print "( statbot ) [ ERROR 03 ] [ BOTID] can't create bmstatbotID file." | |
print "( statbot ) [ ERROR 03 ] check your filesystem policy. exiting." | |
sys.exit() | |
if os.path.isfile("statbot/bmstatbotID.dat"): | |
try: | |
readID = open("statbot/bmstatbotID.dat", "r") | |
botID = readID.read() | |
readID.close() | |
print "( statbot ) ( BOTID ) retrieved botID: ", botID | |
#return botID | |
except: | |
print "( statbot ) [ ERROR 04 ] can't access bmstatbotID file." | |
return botID | |
# this botID will be for reports and will be important in later versions. | |
getBotID() | |
# check ticket counter file; create file if necessary | |
def pingPongCount(type): | |
if type == "ping": | |
filename = "statbot/statbot_PING_counter.dat" | |
if type == "pong": | |
filename = "statbot/statbot_PONG_counter.dat" | |
if type == "bonk": | |
filename = "statbot/statbot_BONK_counter.dat" | |
print "( statbot ) checking ( ", type, " ) counter." | |
if not os.path.isfile(filename): | |
try: | |
makeCounter = open(filename, "w") | |
makeCounter.write("0") | |
makeCounter.close() | |
print "( statbot ) created new ( ", type, " ) counter file." | |
except: | |
print "( statbot ) [ ERROR 05 ] ( ", type, " ) can't create counter file." | |
if os.path.isfile(filename): | |
try: | |
readCounter = open(filename, "r") | |
totalServed = readCounter.read() | |
readCounter.close() | |
except: | |
print "( statbot ) [ ERROR 06 ] ( counter ) ( ", type, " ) can't access file." | |
try: | |
numberServed = int(totalServed) # if can't convert to int() must be corrupted. | |
except ValueError: | |
print "( statbot ) [ ERROR 07 ] ( counter ) file was corrupted, replacing it." | |
numberServed = 0 | |
numberServed += 1 | |
newCount = str(numberServed) | |
try: | |
writeCounter = open(filename, "w") | |
writeCounter.write(newCount) | |
writeCounter.close() | |
print "( statbot ) ( counter ) ( ", type, " ) ( # ", newCount, " )" | |
#return newCount | |
except: | |
print "( statbot ) [ ERROR 08 ] ( counter ) ( ", type, " ) can't write to file." | |
return newCount | |
def sendPong(timeString, sub, msg): | |
print "( statbot ) ( pong ) composing message." | |
address = getAddress("stat_ping", 4, 1) | |
print "( statbot ) ( pong ) ( address ) ", address | |
plainSubject = "PONG " + timeString | |
print "( statbot ) ( pong ) ( subject ) ", plainSubject | |
plainMessage = sub + " " + msg | |
message = plainMessage.encode('base64') | |
subject = plainSubject.encode('base64') | |
ttl = 3600 | |
try: | |
ackData = api.sendMessage(address, address, subject, message, 2, ttl) | |
print "( statbot ) ( pong ) ( status ) ", api.getStatus(ackData) | |
print "( statbot ) ( pong ) ( # ", newCount, " ) sent." | |
except: | |
print "( statbot ) [ ERROR 09] ( pong ) ( api error ) could not send pong." | |
newCount = pingPongCount("pong") | |
# I did not code exceptions for following file access, since if the first round | |
# did not halt the program, everything should be ok - will update it eventually. | |
def dumpMsg(timeString, sub, msg): | |
print " ( statbot ) ( dump ) ( ", sub[:4], " ) get data from inbound message." | |
if sub[:4] == "PING": | |
filename = "statbot/statbot_PING_dump.dat" | |
elif sub[:4] == "PONG": | |
filename = "statbot/statbot_PONG_dump.dat" | |
elif sub[:4] == "BONK": | |
filename = "statbot/statbot_BONK_dump.dat" | |
elif sub[:4] != "PING": | |
print "( statbot ) [ ERROR 10 ] ( dump ) ( garbage ) looks like we got garbage!" | |
print "( statbot ) [ ERROR 10 ] ( dump ) ( garbage ) ( ", sub[:40], " )" | |
print "( statbot ) [ ERROR 10 ] ( dump ) ( garbage ) logged to statbottrash.dat" | |
filename = "statbot/statbottrash.dat" | |
if not os.path.isfile(filename): | |
try: | |
g = open(filename, "w") | |
g.write("") | |
g.close() | |
except: | |
print "( statbot ) [ ERROR 11 ] ( dump ) ( ", sub[:4], " ) can't create file" | |
print "( statbot ) [ ERROR 11 ] ( dump ) exiting." | |
sys.exit() | |
if os.path.isfile(filename): | |
try: | |
lineString = timeString + " " + sub + " " + msg + "\n" | |
h = open(filename, "a") | |
h.write(lineString) | |
h.close() | |
except: | |
print "( statbot ) [ ERROR 12 ] ( dump ) ( ", sub[:4], " ) can't write to file" | |
print "( statbot ) [ ERROR 12 ] ( dump ) exiting." | |
sys.exit() | |
botID = getBotID() | |
if sub[:4] == "PING" and str(getBotID()) not in msg: | |
sendPong(timeString, sub, msg) | |
# Delete the first message from the JSON object, index[0]. | |
def delMsg0(): | |
global api | |
address = getAddress("stat_ping", 4, 1) | |
inboxMessages = json.loads(api.getInboxMessagesByReceiver(address)) | |
numMessages = len(inboxMessages['inboxMessages']) | |
if (numMessages > 0): | |
# Get the msgid of the first message, which is a hex number. | |
msgID = inboxMessages['inboxMessages'][0]['msgid'] | |
print "( statbot ) ( delete ) ", str(msgID)[:55] | |
api.trashMessage(msgID) | |
return "Deleted first message." | |
# Get the first message from the JSON object, index[0] | |
def getMsg0(): | |
global api | |
numMessages = 1 | |
while numMessages > 0: | |
# removed api connection string from here and made it a global so it can | |
# be in top of file for easy install reference | |
address = getAddress("stat_ping", 4, 1) | |
inboxMessages = json.loads(api.getInboxMessagesByReceiver(address)) | |
numMessages = len(inboxMessages['inboxMessages']) | |
print "( statbot ) ( get msg ) ( total ) " + str(numMessages) | |
if (numMessages < 1): | |
print "( statbot ) ( get msg ) ( total ) [0] zero messages to review." | |
if (numMessages > 0): | |
timeString = str(time.time())[:10] | |
msgID = inboxMessages['inboxMessages'][0]['msgid'] | |
print "( statbot ) ( get msg ) ( msgid ) ", msgID[:45] | |
frm = inboxMessages['inboxMessages'][0]['fromAddress'] | |
print "( statbot ) ( get msg ) ( from )", frm[:55] | |
sub = inboxMessages['inboxMessages'][0]['subject'].decode('base64') | |
print "( statbot ) ( get msg ) ( subject ) ", sub[:45] | |
msg = inboxMessages['inboxMessages'][0]['message'].decode('base64') | |
print "( statbot ) ( get msg ) ( message ) ", msg[:45] | |
command = inboxMessages['inboxMessages'][0]['subject'].decode('base64')[:4] | |
print "( statbot ) ( get msg ) ( message ) ( type ) ( ", command, " )" | |
dumpMsg(timeString, sub, msg) | |
delMsg0() | |
def sendPing(): | |
print "( statbot ) ( ping ) generating message." | |
address = getAddress("stat_ping", 4, 1) | |
print "( statbot ) ( ping ) ( address ) ", address | |
timeStamp=time.time() | |
timeString = str(timeStamp) | |
timeSecs = timeString[:10] | |
print "( statbot ) ( ping ) ( time ) ", timeSecs | |
botID = getBotID() | |
lo = 100000000000000000000000 | |
hi = 999999999999999999999999 | |
msgNum = random.randrange(lo, hi) | |
msgNum = str(hex(msgNum)).strip("L")[2:18] | |
print "( statbot ) ( ping ) ( identifier ) ", msgNum | |
plainSubject = "PING " + timeSecs | |
print "( statbot ) ( ping ) ( subject ) ", plainSubject | |
plainMessage = msgNum + " " + str(getBotID()) | |
message = plainMessage.encode('base64') | |
subject = plainSubject.encode('base64') | |
ttl = 3600 | |
try: | |
ackData = api.sendMessage(address, address, subject, message, 2, ttl) | |
print "( statbot ) ( ping ) ( status ) ", api.getStatus(ackData) | |
except: | |
print "( statbot ) [ ERROR ] ( ping ) ( api ) API Error." | |
newCount = pingPongCount("ping") | |
print "( statbot ) ( ping ) ( counter ) ( # ", newCount, " )" | |
def garbageCleanup(): | |
for gc in range (0, 3): | |
getMsg0() | |
print "( statbot ) ( cleanup ) garbage cleanup complete." | |
# generate and send statistical report every 100-300 cycles. | |
def sendBonk(): | |
print "( statbot ) ( bonk ) generating statistical report." | |
botID = str(getBotID()) | |
botID = botID.strip("\n") | |
print "( statbot ) ( bonk ) ( bot ID ) ", botID | |
file = "statbot/statbot_PONG_dump.dat" | |
if not os.path.isfile(file): | |
print "( statbot ) ( bonk ) ( file ) ( ", file, " ) not found." | |
if os.path.isfile(file): | |
fastestPing = 999999 | |
fastestPong = 999999 | |
fastestTrip = 999999 | |
longestPing = 0 | |
longestPong = 0 | |
longestTrip = 0 | |
avgPing = 0 | |
avgPong = 0 | |
avgTrip = 0 | |
totalTransitTime = 0 | |
totalPingPongs = 0 | |
with open(file) as fileobject: | |
for line in fileobject: | |
line = line.strip("\n") | |
columns = line.split(" ") | |
entries = len(columns) | |
#print "# of columns in bonk: " + str(entries) | |
if entries == 7 and str(botID) == str(columns[6]): | |
print "( statbot ) ( bonk ) ( entry ) ( ", botID, " ) ( ", columns[6], " )" | |
try: | |
iPinged = int(columns[4]) | |
theyPonged = int(columns[2]) | |
iBonked = int(columns[0]) | |
except ValueError: | |
print "( statbot ) [ ERROR ] ( bonk ) ( not integer ) corrupt dump data." | |
#print iPinged, theyPonged, iBonked | |
outTime = theyPonged - iPinged | |
backTime = iBonked - theyPonged | |
roundTime = iBonked - iPinged | |
avgPing += outTime | |
avgPong += backTime | |
avgTrip += roundTime # figure this with totalTransitTime / totalPingPongs | |
totalTransitTime += roundTime | |
totalPingPongs += 1 | |
if outTime < fastestPing: | |
fastestPing = outTime | |
if backTime < fastestPong: | |
fastestPong = backTime | |
if roundTime < fastestTrip: | |
fastestTrip = roundTime | |
if outTime > longestPing: | |
longestPing = outTime | |
if backTime > longestPong: | |
longestPong = backTime | |
if roundTime > longestTrip: | |
longestTrip = roundTime | |
fileobject.close() | |
if totalPingPongs > 0: # prevent division by zero error | |
avgTrip = avgTrip / totalPingPongs | |
avgPing = avgPing / totalPingPongs | |
avgPong = avgPong / totalPingPongs | |
print "( statbot ) ( bonk ) ( report ) ( fastestPing ) ", str(fastestPing) | |
print "( statbot ) ( bonk ) ( report ) ( fastestPong ) ", str(fastestPong) | |
print "( statbot ) ( bonk ) ( report ) ( fastestTrip ) ", str(fastestTrip) | |
print "( statbot ) ( bonk ) ( report ) ( longestPing ) ", str(longestPing) | |
print "( statbot ) ( bonk ) ( report ) ( longestPong ) ", str(longestPong) | |
print "( statbot ) ( bonk ) ( report ) ( longestTrip ) ", str(longestTrip) | |
print "( statbot ) ( bonk ) ( report ) ( avgPing ) ", str(avgPing) | |
print "( statbot ) ( bonk ) ( report ) ( avgPong ) ", str(avgPong) | |
print "( statbot ) ( bonk ) ( report ) ( avgTrip ) ", str(avgTrip) | |
print "( statbot ) ( bonk ) ( report ) ( totalTransitTime ) ", str(totalTransitTime) | |
print "( statbot ) ( bonk ) ( report ) ( totalPingPongs ) ", str(totalPingPongs) | |
sub = "BONK " + str(botID) | |
msg = "fastestPing " + str(fastestPing) + "\n" | |
msg += "fastestPong " + str(fastestPong) + "\n" | |
msg += "fastestTrip " + str(fastestTrip) + "\n" | |
msg += "longestPing " + str(longestPing) + "\n" | |
msg += "longestPong " + str(longestPong) + "\n" | |
msg += "longestTrip " + str(longestTrip) + "\n" | |
msg += "avgPing " + str(avgPing) + "\n" | |
msg += "avgPong " + str(avgPong) + "\n" | |
msg += "avgTrip " + str(avgTrip) + "\n" | |
msg += "totalTransitTime " + str(totalTransitTime) + "\n" | |
msg += "totalPingPongs " + str(totalPingPongs) + "\n" | |
print "( statbot ) ( bonk ) ( report ) generating message." | |
address = getAddress("stat_bonk", 4, 1) | |
print "( statbot ) ( bonk ) ( report ) ( address ) ", address | |
message = msg.encode('base64') | |
subject = sub.encode('base64') | |
ttl = 3600 | |
try: | |
ackData = api.sendMessage(address, address, subject, message, 2, ttl) | |
print "( statbot ) ( bonk ) ( report ) ( message ) ( status ) ", api.getStatus(ackData) | |
except: | |
print "( statbot ) ( bonk ) ( report ) ( message ) ( api ) API Error." | |
newCount = pingPongCount("bonk") | |
print "( statbot ) ( bonk ) ( report ) ( message ) ( # ", newCount, " )" | |
def run_statbot(): | |
try: | |
apiTest() | |
print "( statbot ) ( run bot ) ( api test ) ( success ) API responds. continuing." | |
except: | |
print "( statbot ) ( run bot ) ( api test ) ( failure ) API unresponsive. exiting." | |
sys.exit() | |
if len(sys.argv) == 2 and "newMessage" == sys.argv[1]: | |
getMsg0() | |
bonk = random.randrange(0, 334) | |
if bonk == 333: | |
print "( statbot ) ( bonk ) ( random ) initiated." | |
sendBonk() | |
print "( statbot ) ( single ) ( done ) single linear run complete." | |
if len(sys.argv) == 2: | |
while "run" in sys.argv[1]: | |
try: | |
os.system('cls' if os.name == 'nt' else 'clear') | |
except: | |
print "( statbot ) ( run ) ( reset ) command not available." | |
pause = random.randrange(900, 1800) | |
print "( statbot ) ( run ) ( random ) ping in ( ", str(pause), " ) seconds." | |
for seconds in range (0, pause): | |
wait(1) | |
sys.stdout.write("\r( statbot ) ( run ) ( wait ) ==> " + str(seconds) + " ") | |
sys.stdout.flush() | |
print "" | |
sendPing() | |
if len(sys.argv) == 2: | |
if sys.argv[1] == "ping": | |
sendPing() | |
if sys.argv[1] == "bonk": | |
sendBonk() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment