Advertisement
the_austria

walrus.py [1.0.1]

Mar 31st, 2013
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.74 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # Distributed under the MIT software license. See
  3. # http://delicatebits.mit-license.org
  4. # (c) by delicatebits, the_austria
  5. # Bugs, Feedback etc. BM-GuRN32ZC5TBmamUMAA9R7Lja1NJWDkRb
  6. # version 1.0.1
  7.  
  8. import sys
  9. from argparse import ArgumentParser
  10. import configparser
  11. import ntpath
  12. import datetime
  13. import xmlrpc.client as xmlrpclib
  14. import json
  15. import imghdr
  16. from base64 import b64encode
  17.  
  18. # Q: What do I put here?
  19. # A: The values for the API https://bitmessage.org/wiki/API_Reference or your Bitmessage path to lookup these values in key.dat
  20. bitmsgpath = ''
  21. api_user = 'felix'
  22. api_pass = 'felix'
  23. api_host = 'localhost'
  24. api_port = '8442'
  25. # Set the default address where messages will send to, otherwise the argument -t has to be specified
  26. # e.g. BM-BbbuVnYuaSY6yjyhfQm5KVrJLqjiyetB (ImageBoard)
  27. defaultRecipient = ''
  28.  
  29. def getDateTimeString():
  30.     return '%s UTC' % (datetime.datetime.utcnow().strftime('%A, %B %d, %H:%M %Y'))
  31.  
  32. def encode(imgpath):
  33.     with open(imgpath, "rb") as f:
  34.         data = f.read()
  35.         return b64encode(data).decode()
  36.  
  37. class BitmessageApiClient():
  38.     def __init__(self):
  39.         if api_user=='' or api_pass=='' or api_host=='' or not api_port:
  40.             if not self.getCredentialsFromKeysFile():
  41.                 print ('Walrus is unable to send messages without access to PyBitmessage\'s API. Exiting.')
  42.                 print ('For help read README.md or https://github.com/delicatebits/walrus/blob/master/README.md')
  43.                 sys.exit(0)
  44.         self.api_addr = 'http://%s:%s@%s:%s/' % (api_user,api_pass,api_host,api_port)
  45.         self.ready = False
  46.         self.api = xmlrpclib.ServerProxy(self.api_addr)
  47.         self.identity = False
  48.         self.addresses = None
  49.         jsn = self.api.listAddresses()
  50.         try:
  51.             self.addresses = json.loads(jsn)
  52.         except:
  53.             print ('An error occurred when connecting!',jsn)
  54.             return
  55.         if len(self.addresses['addresses']) == 0:
  56.             print ('You must have at least one valid Identity in PyBitmessage')
  57.             #userinput = input('Would you like to create a Random Identity now? [y/N]: ').lower()
  58.             #if 'yes' not in userinput and 'y' not in userinput:
  59.             #    return
  60.             #self.createRandomIdentity();
  61.         else:
  62.             self.addresses = self.addresses['addresses']
  63.             self.ready = True
  64.  
  65.     def createRandomIdentity(self):
  66.         """not yet ready"""
  67.         print ('Warning: Make sure you aren\'t currently creating an Identity in the GUI')
  68.         ripe18 = False
  69.         userinput = input('Spend extra time for a shorter address? [y/N]: ').lower()
  70.         if 'y' in userinput: ripe18 = True
  71.         label = 'Generated by Walrus'
  72.         userinput = input('Enter a label. Default=%s: '%label)
  73.         if len(userinput) > 0: label = userinput
  74.         self.identity = self.api.createRandomAddress(b64encode(label),ripe18)
  75.         print (self.identity)
  76.        
  77.     def isReady(self):
  78.         return self.ready
  79.    
  80.     def lookupBitmessageDataFolder(self):
  81.         from os import path, environ
  82.         if sys.platform == 'darwin':
  83.             if "HOME" in environ:
  84.                 bitmessagedata = path.join(os.environ["HOME"], "Library/Application support/PyBitmessage") + '/'
  85.             else:
  86.                 print ('Could not find home folder, please report this message and your OS X version to the BitMessage Github.')
  87.                 sys.exit()
  88.         elif 'win32' in sys.platform or 'win64' in sys.platform:
  89.             bitmessagedata = path.join(environ['APPDATA'], "PyBitmessage") + '\\'
  90.         else:
  91.             bitmessagedata = path.expanduser(path.join("~", ".PyBitmessage/"))
  92.         return bitmessagedata
  93.    
  94.     def getCredentialsFromKeysFile(self):
  95.         if bitmsgpath != '':
  96.             bitmessagedata = bitmsgpath
  97.         else:
  98.             bitmessagedata = self.lookupBitmessageDataFolder()
  99.         config = configparser.SafeConfigParser()
  100.         config.read(bitmessagedata + 'keys.dat')
  101.         try:
  102.             global api_user,api_pass,api_host,api_port
  103.             api_user = config.get('bitmessagesettings', 'apiusername')
  104.             api_pass = config.get('bitmessagesettings', 'apipassword')
  105.             api_host = config.get('bitmessagesettings', 'apiinterface')
  106.             api_port = config.get('bitmessagesettings', 'apiport')
  107.         except:
  108.             print ('Walrus was unable to read %s' % (bitmessagedata + 'keys.dat') )
  109.             return False
  110.         return True
  111.    
  112.     def getIdentityAddress(self):
  113.         return self.identity['address']
  114.    
  115.     def identityIsSet(self):
  116.         if self.identity != False:
  117.             return True
  118.         return False
  119.  
  120.     def getIdentity(self):
  121.         if not self.ready: return False
  122.         idcnt = 0;
  123.         for x in self.addresses:
  124.             if x['enabled'] != True:
  125.                 idcnt += 1
  126.                 continue;
  127.             print ("[ID: %s]\tAddress: %s\tLabel: %s" % (idcnt,x['address'],x['label']))
  128.             idcnt += 1
  129.         userinput = input('Choose an ID: ')
  130.         try:
  131.             i = int(userinput)
  132.         except ValueError:
  133.             print ('%s is an invalid choice.' % userinput)
  134.             return False
  135.         if len(self.addresses)-1 < i:
  136.             print ('%s is an invalid choice.' % i)
  137.             return False
  138.         self.identity = self.addresses[int(userinput)]
  139.         print ('Message will be sent as %s, %s' % (self.identity['label'],self.identity['address']))
  140.         return True
  141.  
  142.     def checkFromIdentity(self,userinput):
  143.         if not self.ready: return False
  144.         for x in self.addresses:
  145.             if x['address'] == userinput or x['label'] == userinput:
  146.                 if x['enabled'] != True:
  147.                     print ('(%s) %s is Disabled!' % (x['label'],x['address']))
  148.                 else:
  149.                     self.identity = x
  150.                     print ('Message will be sent as %s, %s' % (self.identity['label'],self.identity['address']))
  151.                     return True
  152.         return False
  153.  
  154.     def sendMessage(self,toAddress,subject,message):
  155.         if not self.ready or not self.identity:
  156.             print ('Unable to send message.')
  157.             return False
  158.         self.api.sendMessage(toAddress, self.identity['address'], subject, message)
  159.         print ('Message sent to %s!' % toAddress)
  160.  
  161.     def sendBroadcast(self,subject,message):
  162.         if not self.ready or not self.identity:
  163.             print ('Unable to send message.')
  164.             return False
  165.         self.api.sendBroadcast(self.identity['address'], subject, message)
  166.         print ('Message broadcasted!')
  167.  
  168. def main():
  169.     global defaultRecipient
  170.     parser = ArgumentParser(usage="usage: %(prog)s filename [options]",
  171.                           version="%(prog)s 0.1")
  172.     parser.add_argument("filename")
  173.     parser.add_argument("-s", "--send", action="store_true", dest="flag_send",
  174.                       default=False, help="Send output to Address")
  175.     parser.add_argument("-b", "--broadcast", action="store_true", dest="flag_broadcast", default=False, help="Broadcast output")
  176.     parser.add_argument("-f", "--from", action="store", dest="flag_from", metavar='FROM',
  177.                       default=False, help="Address/Label to send from")
  178.     parser.add_argument("-t", "--to", action="store", dest="flag_to", metavar='TO',
  179.                       default=defaultRecipient, help="Address/Label to send to. Default is %%default")
  180.     parser.add_argument("-u", "--subject", action="store", dest="flag_subject", metavar='SUBJECT',
  181.                       default=False, help="Subject of the message. Default is image name.")
  182.     args = vars(parser.parse_args())
  183.  
  184.     if args['filename']:
  185.         file_path = args['filename']
  186.         file_name = ntpath.basename(file_path)
  187.     else:
  188.         print ('Error: Path to image must be provided')
  189.         return
  190.  
  191.     try:
  192.         with open(file_path): pass
  193.     except IOError:
  194.         print ('%s was not found on your filesystem!' % file_path)
  195.         return
  196.  
  197.     filetype = imghdr.what(file_path)
  198.     if filetype is None:
  199.         print ('%s Does not appear to be an image.' % file_path)
  200.         return;
  201.     else:
  202.         print ('%s is of type: %s' % (file_name, filetype))
  203.  
  204.     encoded = encode(file_path)
  205.     api = None
  206.    
  207.     if not args['flag_send'] and not args['flag_broadcast']:
  208.         print ('Base64 Encoded Image:\n%s' % encoded)
  209.         return
  210.  
  211.     apiClient = BitmessageApiClient()
  212.     if not apiClient.isReady():
  213.         print ('There was an error with the API. Please check your credentials, and make sure you have at least 1 Identity')
  214.         return
  215.    
  216.     if args['flag_from'] != False:
  217.         if not apiClient.checkFromIdentity(args['flag_from']):
  218.             print ('Invalid From Address/Label provided.')
  219.     if not apiClient.identityIsSet():
  220.         if not apiClient.getIdentity():
  221.             return
  222.        
  223.     if args['flag_to'] != defaultRecipient:
  224.         print ('To Addresses/Labels are not validated, yet')
  225.         userinput = input('Are you sure you want to send a message to %s [y/N]: ' % args['flag_to']).lower()
  226.         if 'yes' not in userinput and 'y' not in userinput:
  227.             print ('Exiting')
  228.             exit(0)
  229.         else:
  230.             defaultRecipient = args['flag_to']
  231.    
  232.     print ('Attempting to generate and send message')
  233.     if not apiClient.isReady() or not apiClient.identityIsSet():
  234.         print ('Something went wrong with the API, exiting.')
  235.         return
  236.    
  237.     message = """<html>
  238. <!-- To view the image, right click on the message to view as HTML -->
  239. <!-- This message was sent via a script using the API. -->
  240. <!--    https://github.com/Bitmessage/PyBitmessage/ -->
  241. <!-- This script can be found at: http://pastebin.com/58txrbsK (python 2) or http://pastebin.com/VS7EPJ7m (python 3)-->
  242. <style type="text/css">
  243.    #header { font-size: 12px; color: #555; }
  244.    #image { max-width: 999px; max-height: 300px; }
  245. </style>
  246. <center>
  247.    <div id="header">
  248.        <p>Sent on %s</p>
  249.    </div>
  250.    <div id="image">
  251.        <img src='data:image/%s;base64, %s' />
  252.    </div>
  253. </center>
  254. </html>""" % (getDateTimeString(), filetype, encoded)
  255.        
  256.     if args['flag_subject'] != False:
  257.         subject = args['flag_subject']
  258.     else:
  259.         subject = file_name
  260.    
  261.     if args['flag_send']:
  262.        apiClient.sendMessage(defaultRecipient,
  263.             b64encode(subject.encode()).decode(),
  264.             b64encode(message.encode()).decode() )
  265.            
  266.     if args['flag_broadcast']:
  267.        apiClient.sendBroadcast(
  268.            b64encode(subject.encode()).decode(),
  269.            b64encode(message.encode()).decode() )
  270.    
  271.     print ('Operations Complete! exiting.')
  272.  
  273. if __name__ == '__main__':
  274.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement