-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathavatar.py
145 lines (106 loc) · 4.04 KB
/
avatar.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/python
import falcon
import database
import cache
import logging
import identicon.identicon as identicon
import io
import os
import sqlite3
from PIL import Image
#logging.basicConfig(filename=os.path.join(os.path.dirname(__file__),'avatar.log'),level=logging.DEBUG)
#logging.basicConfig(level=logging.DEBUG)
class Avatar(object):
def put_photo_in_cache(self, email_hash, size, photo):
logging.debug("put photo for hash %s with size %d into cache", email_hash, size)
cache_con = cache.connect_cache()
c = cache_con.cursor()
c.execute("INSERT INTO cache (email_hash, size, photo) VALUES (?, ?, ?)", [email_hash, size, sqlite3.Binary(photo)])
cache_con.commit()
cache_con.close()
def get_photo_from_cache(self, email_hash, size):
found = False
photo = None
cache_con = cache.connect_cache()
c = cache_con.cursor()
c.execute("SELECT photo FROM cache WHERE email_hash = ? AND size = ?", [email_hash,size])
photodata = c.fetchone()
if photodata:
found = True
photo = bytes(photodata[0])
cache_con.close()
return (found, photo)
def get_photo_from_db(self, email_hash):
found = False
photo = None
db = database.connect_db()
c = db.cursor()
c.execute("SELECT photo_hash FROM emails WHERE email_hash = ?", [email_hash])
photo_hash = c.fetchone()
if photo_hash:
c.execute("SELECT photo FROM photos WHERE photo_hash = ?", [photo_hash[0]])
photodata = c.fetchone()
if photodata:
found = True
photo = bytes(photodata[0])
db.close()
return (found, photo)
def resize_and_square(self, photo, size):
file_in = io.BytesIO(photo)
file_in.seek(0)
img = Image.open(file_in)
#from: http://javiergodinez.blogspot.de/2008/03/square-thumbnail-with-python-image.html
width, height = img.size
if width > height:
delta = width - height
left = int(delta/2)
upper = 0
right = height + left
lower = height
else:
delta = height - width
left = 0
upper = int(delta/2)
right = width
lower = width + upper
img = img.crop((left, upper, right, lower))
img.thumbnail((size,size))
file_out = io.BytesIO()
img.save(file_out, 'PNG')
return file_out.getvalue()
def on_get(self, req, resp, email_hash):
resp.content_type = "image/png"
#cut possible extensions, we do not support them
email_hash = email_hash[:32]
size = 80
if req.get_param("s"):
size = int(req.get_param("s"))
if req.get_param("size"):
size = int(req.get_param("size"))
# look for photo in cache
found, photo = self.get_photo_from_cache(email_hash, size)
if found:
#logging.debug("hash %s with size %d found in cache", email_hash, size)
pass
else:
# photo not found in cache, look in db
found, photo = self.get_photo_from_db(email_hash)
if found:
logging.debug("hash %s found in db", email_hash)
photo = self.resize_and_square(photo, size)
self.put_photo_in_cache(email_hash, size, photo)
else:
# photo not found in db, render identicon
logging.debug("hash %s NOT found, rendering identicon", email_hash)
code = abs(hash(email_hash)) % (10 ** 8)
icon = identicon.render_identicon(code, size)
icon.thumbnail((size,size))
b = io.BytesIO()
icon.save(b, 'PNG')
photo = b.getvalue()
self.put_photo_in_cache(email_hash, size, photo)
resp.status = falcon.HTTP_200
resp.body = photo
# entry
api = application = falcon.API()
api.add_route('/{email_hash}', Avatar())