utils.py
1 import hashlib 2 import os 3 4 from PyQt4 import QtGui 5 6 import state 7 from addresses import addBMIfNotPresent 8 from bmconfigparser import config 9 10 str_broadcast_subscribers = '[Broadcast subscribers]' 11 str_chan = '[chan]' 12 13 14 def identiconize(address): 15 size = 48 16 17 if not config.getboolean('bitmessagesettings', 'useidenticons'): 18 return QtGui.QIcon() 19 20 # If you include another identicon library, please generate an 21 # example identicon with the following md5 hash: 22 # 3fd4bf901b9d4ea1394f0fb358725b28 23 24 identicon_lib = config.safeGet( 25 'bitmessagesettings', 'identiconlib', 'qidenticon_two_x') 26 27 # As an 'identiconsuffix' you could put "@bitmessge.ch" or "@bm.addr" 28 # to make it compatible with other identicon generators. (Note however, 29 # that E-Mail programs might convert the BM-address to lowercase first.) 30 # It can be used as a pseudo-password to salt the generation of 31 # the identicons to decrease the risk of attacks where someone creates 32 # an address to mimic someone else's identicon. 33 identiconsuffix = config.get('bitmessagesettings', 'identiconsuffix') 34 if identicon_lib[:len('qidenticon')] == 'qidenticon': 35 # originally by: 36 # :Author:Shin Adachi <shn@glucose.jp> 37 # Licesensed under FreeBSD License. 38 # stripped from PIL and uses QT instead (by sendiulo, same license) 39 import qidenticon 40 icon_hash = hashlib.md5( 41 addBMIfNotPresent(address) + identiconsuffix).hexdigest() 42 use_two_colors = identicon_lib[:len('qidenticon_two')] == 'qidenticon_two' 43 opacity = int( 44 identicon_lib not in ( 45 'qidenticon_x', 'qidenticon_two_x', 46 'qidenticon_b', 'qidenticon_two_b' 47 )) * 255 48 penwidth = 0 49 image = qidenticon.render_identicon( 50 int(icon_hash, 16), size, use_two_colors, opacity, penwidth) 51 # filename = './images/identicons/'+hash+'.png' 52 # image.save(filename) 53 idcon = QtGui.QIcon() 54 idcon.addPixmap(image, QtGui.QIcon.Normal, QtGui.QIcon.Off) 55 return idcon 56 elif identicon_lib == 'pydenticon': 57 # Here you could load pydenticon.py 58 # (just put it in the "src" folder of your Bitmessage source) 59 from pydenticon import Pydenticon 60 # It is not included in the source, because it is licensed under GPLv3 61 # GPLv3 is a copyleft license that would influence our licensing 62 # Find the source here: 63 # https://github.com/azaghal/pydenticon 64 # note that it requires pillow (or PIL) to be installed: 65 # https://python-pillow.org/ 66 idcon_render = Pydenticon( 67 addBMIfNotPresent(address) + identiconsuffix, size * 3) 68 rendering = idcon_render._render() 69 data = rendering.convert("RGBA").tostring("raw", "RGBA") 70 qim = QtGui.QImage(data, size, size, QtGui.QImage.Format_ARGB32) 71 pix = QtGui.QPixmap.fromImage(qim) 72 idcon = QtGui.QIcon() 73 idcon.addPixmap(pix, QtGui.QIcon.Normal, QtGui.QIcon.Off) 74 return idcon 75 76 77 def avatarize(address): 78 """ 79 Loads a supported image for the given address' hash form 'avatars' folder 80 falls back to default avatar if 'default.*' file exists 81 falls back to identiconize(address) 82 """ 83 idcon = QtGui.QIcon() 84 icon_hash = hashlib.md5(addBMIfNotPresent(address)).hexdigest() 85 if address == str_broadcast_subscribers: 86 # don't hash [Broadcast subscribers] 87 icon_hash = address 88 # https://www.riverbankcomputing.com/static/Docs/PyQt4/qimagereader.html#supportedImageFormats 89 # QImageReader.supportedImageFormats () 90 extensions = [ 91 'PNG', 'GIF', 'JPG', 'JPEG', 'SVG', 'BMP', 'MNG', 'PBM', 'PGM', 'PPM', 92 'TIFF', 'XBM', 'XPM', 'TGA'] 93 # try to find a specific avatar 94 for ext in extensions: 95 lower_hash = state.appdata + 'avatars/' + icon_hash + '.' + ext.lower() 96 upper_hash = state.appdata + 'avatars/' + icon_hash + '.' + ext.upper() 97 if os.path.isfile(lower_hash): 98 idcon.addFile(lower_hash) 99 return idcon 100 elif os.path.isfile(upper_hash): 101 idcon.addFile(upper_hash) 102 return idcon 103 # if we haven't found any, try to find a default avatar 104 for ext in extensions: 105 lower_default = state.appdata + 'avatars/' + 'default.' + ext.lower() 106 upper_default = state.appdata + 'avatars/' + 'default.' + ext.upper() 107 if os.path.isfile(lower_default): 108 default = lower_default 109 idcon.addFile(lower_default) 110 return idcon 111 elif os.path.isfile(upper_default): 112 default = upper_default 113 idcon.addFile(upper_default) 114 return idcon 115 # If no avatar is found 116 return identiconize(address)