Advertisement
the_austria

walrus.py [1.0.1] [Python 2]

May 15th, 2013
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.56 KB | None | 0 0
  1. #!/usr/bin/env python2.7
  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 optparse import OptionParser
  10. import ConfigParser
  11. import ntpath
  12. import datetime
  13. import xmlrpclib
  14. import json
  15. import imghdr
  16.  
  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 = ''
  22. api_pass = ''
  23. api_host = ''
  24. api_port = ''
  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 %G'))
  31.  
  32. def encode(imgpath):
  33.     with open(imgpath, "rb") as f:
  34.         data = f.read()
  35.         return data.encode("base64")
  36.  
  37. class BitmessageApiClient():
  38.     def __init__(self):
  39.         if api_user=='' or api_host=='' or 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 = raw_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 = raw_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 = raw_input('Enter a label. Default=%s: '%label)
  73.         if len(userinput) > 0: label = userinput
  74.         self.identity = self.api.createRandomAddress(label.encode('base64'),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(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 = raw_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!' % defaultRecipient
  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 = OptionParser(usage="usage: %prog filename [options]",
  171.                           version="%prog 0.1")
  172.     parser.add_option("filename")
  173.     parser.add_option("-s", "--send", action="store_true", dest="flag_send",
  174.                       default=False, help="Send output to Address")
  175.     parser.add_option("-b", "--broadcast", action="store_true", dest="flag_broadcast", default=False, help="Broadcast output")
  176.     parser.add_option("-f", "--from", action="store", dest="flag_from", metavar='FROM',
  177.                       default=False, help="Address/Label to send from")
  178.     parser.add_option("-t", "--to", action="store", dest="flag_to", metavar='TO',
  179.                       default=defaultRecipient, help="Address/Label to send to. Default is %default")
  180.     parser.add_option("-u", "--subject", action="store", dest="flag_subject", metavar='SUBJECT',
  181.                       default=False, help="Subject of the message. Default is image name.")
  182.     (options, args) = parser.parse_args()
  183.  
  184.     if len(args) == 1:
  185.         file_path = args[0]
  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 options.flag_send and not options.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 options.flag_from != False:
  217.         if not apiClient.checkFromIdentity(options.flag_from):
  218.             print 'Invalid From Address/Label provided.'
  219.     if not apiClient.identityIsSet():
  220.         if not apiClient.getIdentity():
  221.             return
  222.        
  223.     if options.flag_to != defaultRecipient:
  224.         print 'To Addresses/Labels are not validated, yet'
  225.         userinput = raw_input('Are you sure you want to send a message to %s [y/N]: ' % options.flag_to).lower()
  226.         if 'yes' not in userinput and 'y' not in userinput:
  227.             print 'Exiting'
  228.             exit(0)
  229.         else:
  230.             defaultRecipient = options.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 options.flag_subject != False:
  257.         subject = options.flag_subject
  258.     else:
  259.         subject = file_name
  260.    
  261.     if options.flag_send:
  262.        apiClient.sendMessage(defaultRecipient,
  263.             subject.encode('base64'),
  264.             message.encode('base64') )
  265.    
  266.     if options.flag_broadcast:
  267.        apiClient.sendBroadcast(
  268.            subject.encode('base64'),
  269.            message.encode('base64') )
  270.            
  271.     print 'Operations Complete! exiting.'
  272.  
  273. if __name__ == '__main__':
  274.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement