#!/usr/bin/python
+import PIL
import datetime
+import imghdr
+import io
import ldap
import logging
-import imghdr
+import os.path
import tornado.web
import urllib.parse
from . import base
from . import ui_modules
+COLOUR_LIGHT = (237,232,232)
+COLOUR_DARK = (49,53,60)
+
class IndexHandler(auth.CacheMixin, base.BaseHandler):
@tornado.web.authenticated
def get(self):
if not avatar:
logging.debug("No avatar uploaded for %s" % account)
- return self.redirect(self.static_url("img/default-avatar.jpg"))
+ # Generate a random avatar with only one letter
+ avatar = self._get_avatar(account, size=size)
# Guess content type
type = imghdr.what(None, avatar)
# Deliver payload
self.finish(avatar)
+ def _get_avatar(self, account, size=None, **args):
+ letter = ("%s" % account)[0].upper()
+
+ if size is None:
+ size = 256
+
+ # The generated avatar cannot be larger than 1024px
+ if size >= 2048:
+ size = 2048
+
+ # Cache key
+ key = "avatar:letter:%s:%s" % (letter, size)
+
+ # Fetch avatar from the cache
+ avatar = self.memcached.get(key)
+ if not avatar:
+ avatar = self._make_avatar(letter, size=size, **args)
+
+ # Cache for forever
+ self.memcached.set(key, avatar)
+
+ return avatar
+
+ def _make_avatar(self, letter, format="PNG", size=None, **args):
+ # Generate an image of the correct size
+ image = PIL.Image.new("RGBA", (size, size), COLOUR_LIGHT)
+
+ # Have a canvas
+ draw = PIL.ImageDraw.Draw(image)
+
+ # Load font
+ font = PIL.ImageFont.truetype(os.path.join(
+ self.application.settings.get("static_path", ""),
+ "fonts/Mukta-Bold.ttf"
+ ), size, encoding="unic")
+
+ # Determine size of the printed letter
+ w, h = font.getsize(letter)
+
+ # Mukta seems to be very broken and the height needs to be corrected
+ h //= 0.7
+
+ # Draw the letter in the center
+ draw.text(((size - w) / 2, (size - h) / 2), letter,
+ font=font, fill=COLOUR_DARK)
+
+ with io.BytesIO() as f:
+ # If writing out the image does not work with optimization,
+ # we try to write it out without any optimization.
+ try:
+ image.save(f, format, optimize=True, **args)
+ except:
+ image.save(f, format, **args)
+
+ return f.getvalue()
+
class CallsHandler(auth.CacheMixin, base.BaseHandler):
@tornado.web.authenticated