2015-10-02 22:24:46 +02:00
|
|
|
import hashlib
|
|
|
|
import os
|
2018-02-26 12:34:10 +01:00
|
|
|
|
|
|
|
from PyQt4 import QtGui
|
|
|
|
|
|
|
|
import state
|
2015-10-02 22:24:46 +02:00
|
|
|
from addresses import addBMIfNotPresent
|
2022-01-28 13:55:23 +01:00
|
|
|
from bmconfigparser import config
|
2015-10-02 22:24:46 +02:00
|
|
|
|
2015-10-13 23:33:36 +02:00
|
|
|
str_broadcast_subscribers = '[Broadcast subscribers]'
|
2016-10-28 22:07:16 +02:00
|
|
|
str_chan = '[chan]'
|
2015-10-13 23:33:36 +02:00
|
|
|
|
2018-02-26 12:34:10 +01:00
|
|
|
|
2015-10-02 22:24:46 +02:00
|
|
|
def identiconize(address):
|
|
|
|
size = 48
|
2018-03-03 16:31:49 +01:00
|
|
|
|
2022-01-28 13:55:23 +01:00
|
|
|
if not config.getboolean('bitmessagesettings', 'useidenticons'):
|
2018-03-03 16:31:49 +01:00
|
|
|
return QtGui.QIcon()
|
|
|
|
|
|
|
|
# If you include another identicon library, please generate an
|
2015-10-02 22:24:46 +02:00
|
|
|
# example identicon with the following md5 hash:
|
|
|
|
# 3fd4bf901b9d4ea1394f0fb358725b28
|
|
|
|
|
2022-01-28 13:55:23 +01:00
|
|
|
identicon_lib = config.safeGet(
|
2018-03-03 16:31:49 +01:00
|
|
|
'bitmessagesettings', 'identiconlib', 'qidenticon_two_x')
|
|
|
|
|
|
|
|
# As an 'identiconsuffix' you could put "@bitmessge.ch" or "@bm.addr"
|
|
|
|
# to make it compatible with other identicon generators. (Note however,
|
|
|
|
# that E-Mail programs might convert the BM-address to lowercase first.)
|
|
|
|
# It can be used as a pseudo-password to salt the generation of
|
|
|
|
# the identicons to decrease the risk of attacks where someone creates
|
|
|
|
# an address to mimic someone else's identicon.
|
2022-01-28 13:55:23 +01:00
|
|
|
identiconsuffix = config.get('bitmessagesettings', 'identiconsuffix')
|
2018-02-26 12:34:10 +01:00
|
|
|
if identicon_lib[:len('qidenticon')] == 'qidenticon':
|
2015-10-02 22:24:46 +02:00
|
|
|
# originally by:
|
|
|
|
# :Author:Shin Adachi <shn@glucose.jp>
|
|
|
|
# Licesensed under FreeBSD License.
|
|
|
|
# stripped from PIL and uses QT instead (by sendiulo, same license)
|
|
|
|
import qidenticon
|
2018-02-26 12:34:10 +01:00
|
|
|
icon_hash = hashlib.md5(
|
2024-05-27 17:12:27 +02:00
|
|
|
(addBMIfNotPresent(address) + identiconsuffix).encode("utf-8", "replace")).hexdigest()
|
2018-02-26 12:34:10 +01:00
|
|
|
use_two_colors = identicon_lib[:len('qidenticon_two')] == 'qidenticon_two'
|
|
|
|
opacity = int(
|
|
|
|
identicon_lib not in (
|
|
|
|
'qidenticon_x', 'qidenticon_two_x',
|
|
|
|
'qidenticon_b', 'qidenticon_two_b'
|
|
|
|
)) * 255
|
2015-10-02 22:24:46 +02:00
|
|
|
penwidth = 0
|
2018-02-26 12:34:10 +01:00
|
|
|
image = qidenticon.render_identicon(
|
|
|
|
int(icon_hash, 16), size, use_two_colors, opacity, penwidth)
|
2015-10-02 22:24:46 +02:00
|
|
|
# filename = './images/identicons/'+hash+'.png'
|
|
|
|
# image.save(filename)
|
|
|
|
idcon = QtGui.QIcon()
|
|
|
|
idcon.addPixmap(image, QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
|
|
|
return idcon
|
|
|
|
elif identicon_lib == 'pydenticon':
|
2018-02-26 12:34:10 +01:00
|
|
|
# Here you could load pydenticon.py
|
|
|
|
# (just put it in the "src" folder of your Bitmessage source)
|
2015-10-02 22:24:46 +02:00
|
|
|
from pydenticon import Pydenticon
|
|
|
|
# It is not included in the source, because it is licensed under GPLv3
|
|
|
|
# GPLv3 is a copyleft license that would influence our licensing
|
2018-02-26 12:34:10 +01:00
|
|
|
# Find the source here:
|
|
|
|
# https://github.com/azaghal/pydenticon
|
|
|
|
# note that it requires pillow (or PIL) to be installed:
|
|
|
|
# https://python-pillow.org/
|
|
|
|
idcon_render = Pydenticon(
|
|
|
|
addBMIfNotPresent(address) + identiconsuffix, size * 3)
|
2015-10-02 22:24:46 +02:00
|
|
|
rendering = idcon_render._render()
|
|
|
|
data = rendering.convert("RGBA").tostring("raw", "RGBA")
|
2017-06-10 10:09:14 +02:00
|
|
|
qim = QtGui.QImage(data, size, size, QtGui.QImage.Format_ARGB32)
|
|
|
|
pix = QtGui.QPixmap.fromImage(qim)
|
2015-10-02 22:24:46 +02:00
|
|
|
idcon = QtGui.QIcon()
|
|
|
|
idcon.addPixmap(pix, QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
|
|
|
return idcon
|
|
|
|
|
2018-02-26 12:34:10 +01:00
|
|
|
|
2015-10-02 22:24:46 +02:00
|
|
|
def avatarize(address):
|
|
|
|
"""
|
2018-02-26 12:34:10 +01:00
|
|
|
Loads a supported image for the given address' hash form 'avatars' folder
|
|
|
|
falls back to default avatar if 'default.*' file exists
|
|
|
|
falls back to identiconize(address)
|
2015-10-02 22:24:46 +02:00
|
|
|
"""
|
|
|
|
idcon = QtGui.QIcon()
|
2024-05-27 17:12:27 +02:00
|
|
|
icon_hash = hashlib.md5(addBMIfNotPresent(address).encode("utf-8", "replace")).hexdigest()
|
2015-10-02 22:24:46 +02:00
|
|
|
if address == str_broadcast_subscribers:
|
|
|
|
# don't hash [Broadcast subscribers]
|
2018-02-26 12:34:10 +01:00
|
|
|
icon_hash = address
|
|
|
|
# https://www.riverbankcomputing.com/static/Docs/PyQt4/qimagereader.html#supportedImageFormats
|
2015-10-02 22:24:46 +02:00
|
|
|
# QImageReader.supportedImageFormats ()
|
2018-02-26 12:34:10 +01:00
|
|
|
extensions = [
|
|
|
|
'PNG', 'GIF', 'JPG', 'JPEG', 'SVG', 'BMP', 'MNG', 'PBM', 'PGM', 'PPM',
|
|
|
|
'TIFF', 'XBM', 'XPM', 'TGA']
|
2015-10-02 22:24:46 +02:00
|
|
|
# try to find a specific avatar
|
|
|
|
for ext in extensions:
|
2018-02-26 12:34:10 +01:00
|
|
|
lower_hash = state.appdata + 'avatars/' + icon_hash + '.' + ext.lower()
|
|
|
|
upper_hash = state.appdata + 'avatars/' + icon_hash + '.' + ext.upper()
|
2015-10-02 22:24:46 +02:00
|
|
|
if os.path.isfile(lower_hash):
|
|
|
|
idcon.addFile(lower_hash)
|
|
|
|
return idcon
|
|
|
|
elif os.path.isfile(upper_hash):
|
|
|
|
idcon.addFile(upper_hash)
|
|
|
|
return idcon
|
|
|
|
# if we haven't found any, try to find a default avatar
|
|
|
|
for ext in extensions:
|
2017-01-11 17:00:00 +01:00
|
|
|
lower_default = state.appdata + 'avatars/' + 'default.' + ext.lower()
|
|
|
|
upper_default = state.appdata + 'avatars/' + 'default.' + ext.upper()
|
2015-10-02 22:24:46 +02:00
|
|
|
if os.path.isfile(lower_default):
|
|
|
|
default = lower_default
|
|
|
|
idcon.addFile(lower_default)
|
|
|
|
return idcon
|
|
|
|
elif os.path.isfile(upper_default):
|
|
|
|
default = upper_default
|
|
|
|
idcon.addFile(upper_default)
|
|
|
|
return idcon
|
|
|
|
# If no avatar is found
|
|
|
|
return identiconize(address)
|