Robohash/webfront.py

418 lines
16 KiB
Python
Raw Normal View History

2011-07-05 15:42:12 -04:00
#!/usr/bin/env python
#
# Copyright 2011 Pluric
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.escape
import socket
import re
2011-07-05 19:31:17 -04:00
import os
2011-08-30 21:57:51 -04:00
import md5
2011-07-05 15:42:12 -04:00
import pprint
import Image
2011-07-05 19:31:17 -04:00
import hashlib
import urllib
2011-07-06 01:41:06 -04:00
import random
2011-08-30 21:57:51 -04:00
import urllib2
2011-07-06 06:39:35 +00:00
from tornado.options import define, options
2011-07-05 15:42:12 -04:00
try:
from hashlib import md5 as md5_func
except ImportError:
from md5 import new as md5_func
2012-07-26 04:56:31 -04:00
import cStringIO
2011-07-05 15:42:12 -04:00
2011-07-06 06:39:35 +00:00
define("port", default=80, help="run on the given port", type=int)
2011-07-05 15:42:12 -04:00
2011-07-05 19:31:17 -04:00
class Robohash(object):
def __init__(self,string):
hash = hashlib.sha512()
hash.update(string)
self.hexdigest = hash.hexdigest()
self.hasharray = []
2011-07-07 18:49:57 -04:00
#Start this at 3, so earlier is reserved
#0 = Color
#1 = Set
#2 = bgset
#3 = BG
self.iter = 4
2011-07-06 01:41:06 -04:00
2011-07-05 19:31:17 -04:00
def createHashes(self,count):
#Create and store a series of hash-values
#Basically, split up a hash (SHA/md5/etc) into X parts
for i in range(0,count):
#Get 1/numblocks of the hash
blocksize = (len(self.hexdigest) / count)
currentstart = (1 + i) * blocksize - blocksize
currentend = (1 +i) * blocksize
self.hasharray.append(int(self.hexdigest[currentstart:currentend],16))
def dirCount(self,path):
#return the count of just the directories beneath me.
return sum([len(dirs) for (root, dirs, files) in os.walk(path)])
2011-07-05 21:31:42 -04:00
def getHashList(self,path):
2011-07-05 19:31:17 -04:00
#Each iteration, if we hit a directory, recurse
#If not, choose the appropriate file, given the hashes, stored above
2011-07-06 01:41:06 -04:00
2011-07-05 19:31:17 -04:00
completelist = []
locallist = []
2011-08-08 20:02:33 +00:00
listdir = os.listdir(path)
listdir.sort()
for ls in listdir:
2011-07-05 19:31:17 -04:00
if not ls.startswith("."):
if os.path.isdir(path + "/" + ls):
2011-07-05 21:31:42 -04:00
subfiles = self.getHashList(path + "/" + ls)
2011-07-05 19:31:17 -04:00
if subfiles is not None:
completelist = completelist + subfiles
else:
locallist.append( path + "/" + ls)
if len(locallist) > 0:
2011-07-05 21:31:42 -04:00
elementchoice = self.hasharray[self.iter] % len(locallist)
2011-07-05 19:31:17 -04:00
luckyelement = locallist[elementchoice]
locallist = []
locallist.append(luckyelement)
2011-07-05 21:31:42 -04:00
self.iter += 1
2011-07-05 19:31:17 -04:00
completelist = completelist + locallist
2011-07-05 21:31:42 -04:00
return completelist
2011-07-05 19:31:17 -04:00
2011-07-05 21:09:08 -04:00
class MainHandler(tornado.web.RequestHandler):
def get(self):
ip = self.request.remote_ip
2011-07-08 03:01:40 -04:00
robo = [
"""
, ,
(\\____/)
(_oo_)
(O)
__||__ \\)
[]/______\\[] /
/ \\______/ \\/
/ /__\\
(\\ /____\\ """,
"""
_______
_/ \\_
/ | | \\
/ |__ __| \\
|__/((o| |o))\\__|
| | | |
|\\ |_| /|
| \\ / |
\\| / ___ \\ |/
\\ | / _ \\ | /
\\_________/
_|_____|_
____|_________|____
/ \\ -- Mark Moir
""",
""" .andAHHAbnn.
.aAHHHAAUUAAHHHAn.
dHP^~" "~^THb.
. .AHF YHA. .
| .AHHb. .dHHA. |
| HHAUAAHAbn adAHAAUAHA |
I HF~"_____ ____ ]HHH I
HHI HAPK""~^YUHb dAHHHHHHHHHH IHH
HHI HHHD> .andHH HHUUP^~YHHHH IHH
YUI ]HHP "~Y P~" THH[ IUP
" `HK ]HH' "
THAn. .d.aAAn.b. .dHHP
]HHHHAAUP" ~~ "YUAAHHHH[
`HHP^~" .annn. "~^YHH'
YHb ~" "" "~ dHF
"YAb..abdHHbndbndAP"
THHAAb. .adAHHF
"UHHHHHHHHHHU"
]HHUUHHHHHH[
.adHHb "HHHHHbn.
..andAAHHHHHHb.AHHHHHHHAAbnn..
.ndAAHHHHHHUUHHHHHHHHHHUP^~"~^YUHHHAAbn.
"~^YUHHP" "~^YUHHUP" "^YUP^"
"" "~~"
""",
""" /~@@~\\,
_______ . _\\_\\___/\\ __ /\\___|_|_ . _______
/ ____ |=| \\ <_+> / |=| ____ \\
~| |\\|=|======\\\\______//======|=|/| |~
|_ | \\ | | / | |
\\==-| \\ | 2D | / |----|~~)
| | | | | | |____/~/
| | \\____\\____/____/ / / /
| | {----------} /____/ /
|___| /~~~~~~~~~~~~\\ |_/~|_|/
\\_/ [/~~~~~||~~~~~\\] /__|\\
| | | |||| | (/|[[\\)
[_] | | | |
|_____| |_____|
(_____) (_____)
| | | |
| | | |
|/~~~\\| |/~~~\\|
/|___|\\ /|___|\\
<_______><_______>""",
""" _____
/_____\\
____[\\`---'/]____
/\\ #\\ \\_____/ /# /\\
/ \\# \\_.---._/ #/ \\
/ /|\\ | | /|\\ \\
/___/ | | | | | | \\___\\
| | | | |---| | | | |
|__| \\_| |_#_| |_/ |__|
//\\\\ <\\ _//^\\\\_ /> //\\\\
\\||/ |\\//// \\\\\\\\/| \\||/
| | | |
|---| |---|
|---| |---|
| | | |
|___| |___|
/ \\ / \\
|_____| |_____|
|HHHHH| |HHHHH|
""",
""" () ()
\\ /
__\\___________/__
/ \\
/ ___ ___ \\
| / \\ / \\ |
2011-07-08 03:01:40 -04:00
| | H || H | |
| \\___/ \\___/ |
2011-07-08 03:01:40 -04:00
| |
| \\ / |
| \\___________/ |
\\ /
\\_________________/
2011-07-08 03:01:40 -04:00
_________|__|_______
_| |_
/ | | \\
/ | O O O | \\
| | | |
| | O O O | |
| | | |
/ | | \\
| /| |\\ |
\\| | | |/
2011-07-08 03:01:40 -04:00
|____________________|
| | | |
|__| |__|
/ __ \\ / __ \\
2011-07-08 03:01:40 -04:00
OO OO OO OO
"""]
self.write(self.render_string('templates/root.html',ip=ip,robo=random.choice(robo)))
2011-07-05 19:31:17 -04:00
class ImgHandler(tornado.web.RequestHandler):
def get(self,string=None):
2011-07-06 01:41:06 -04:00
colors = ['blue','brown','green','grey','orange','pink','purple','red','white','yellow']
sets = ['set1','set2','set3']
2011-07-07 18:49:57 -04:00
bgsets = ['bg1','bg2']
2011-07-06 01:41:06 -04:00
2011-07-05 19:31:17 -04:00
#Create a hash for the string as given
if string is None:
string = self.request.remote_ip
2011-08-30 21:57:51 -04:00
# string = urllib.quote_plus(string)
2011-07-16 00:23:55 -04:00
if "ignoreext" in self.request.arguments:
client_ignoreext = tornado.escape.xhtml_escape(self.get_argument("ignoreext"))
else:
client_ignoreext = None
2011-08-30 16:35:59 -04:00
#Change to a usuable format
2012-07-26 04:56:31 -04:00
if string.endswith(('.png','.gif','.jpg','.bmp','.jpeg','.ppm','.datauri')):
2011-08-30 16:35:59 -04:00
ext = string[string.rfind('.') +1 :len(string)]
if ext.lower() == 'jpg':
ext = 'jpeg'
else:
ext = "png"
if client_ignoreext != "false":
2012-07-27 13:26:14 -04:00
if string.endswith(('.png','.gif','.jpg','.bmp','.jpeg','.ppm','.datauri')):
2011-07-16 00:23:55 -04:00
string = string[0:string.rfind('.')]
2011-07-05 19:31:17 -04:00
r = Robohash(string)
2011-07-16 00:23:55 -04:00
2011-07-06 01:41:06 -04:00
#Create 10 hashes. This should be long enough for the current crop of variables.
#This is probably not insecure, sicne we'd be modding anyway. This just spreads it out more.
2011-07-07 18:49:57 -04:00
r.createHashes(11)
2011-07-06 01:41:06 -04:00
2011-07-06 02:31:34 -04:00
2011-07-06 01:41:06 -04:00
#Now, customize the request if possible.
client_color = ""
2011-07-06 02:31:34 -04:00
client_set = ""
2011-07-07 18:49:57 -04:00
client_bgset = ""
sizex = 300
sizey = 300
2011-07-16 00:23:55 -04:00
2011-07-07 18:49:57 -04:00
if "size" in self.request.arguments:
sizelist = self.get_argument("size").split(tornado.escape.xhtml_escape("x"),3)
if ((int(sizelist[0]) > 0) and (int(sizelist[0]) < 4096)):
sizex = int(sizelist[0])
if ((int(sizelist[0]) > 0) and (int(sizelist[0]) < 4096)):
sizey = int(sizelist[1])
2011-08-30 21:57:51 -04:00
if "gravatar" in self.request.arguments:
if tornado.escape.xhtml_escape(self.get_argument("gravatar")) == 'yes':
default = "404"
# construct the url
2012-09-23 02:56:07 +00:00
gravatar_url = "https://secure.gravatar.com/avatar/" + hashlib.md5(string.lower()).hexdigest() + "?"
2011-12-11 02:00:56 +00:00
gravatar_url += urllib.urlencode({'default':default, 'size':str(sizey)})
2011-08-30 22:47:50 -04:00
if tornado.escape.xhtml_escape(self.get_argument("gravatar")) == 'hashed':
2011-08-30 23:04:30 -04:00
string = urllib.quote(string)
2011-08-30 22:47:50 -04:00
default = "404"
# construct the url
2012-09-23 02:56:07 +00:00
gravatar_url = "https://secure.gravatar.com/avatar/" + string + "?"
2011-12-11 02:00:56 +00:00
gravatar_url += urllib.urlencode({'default':default, 'size':str(sizey)})
2011-08-30 22:47:50 -04:00
try:
f = urllib2.urlopen(urllib2.Request(gravatar_url))
self.redirect(gravatar_url, permanent=False)
return 0
except:
badGravatar = True
2011-08-30 21:57:51 -04:00
2011-07-06 01:41:06 -04:00
if "set" in self.request.arguments:
2011-07-07 18:49:57 -04:00
if tornado.escape.xhtml_escape(self.get_argument("set")) == 'any':
client_set = sets[r.hasharray[1] % len(sets) ]
if self.get_argument("set") in sets:
client_set = tornado.escape.xhtml_escape(self.get_argument("set"))
else:
#If no set specified, you get set 1
client_set = "set1"
2011-07-16 00:39:27 -04:00
##Let people define multiple sets, so I can add more.
if "sets" in self.request.arguments:
newsets = tornado.escape.xhtml_escape(self.get_argument("sets")).split(",");
replaceset = []
for s in newsets:
if s in sets:
replaceset.append(s)
client_set = replaceset[r.hasharray[1] % len(replaceset) ]
2011-07-07 18:49:57 -04:00
if client_set == 'set1':
client_set = colors[r.hasharray[0] % len(colors) ]
2011-07-06 02:31:34 -04:00
if "color" in self.request.arguments:
if self.get_argument("color") in colors:
client_set = tornado.escape.xhtml_escape(self.get_argument("color"))
2011-07-07 18:49:57 -04:00
if "bgset" in self.request.arguments:
if self.get_argument("bgset") in bgsets:
client_bgset = tornado.escape.xhtml_escape(self.get_argument("bgset"))
else:
client_bgset = bgsets[r.hasharray[2] % len(bgsets) ]
2011-07-18 21:47:54 +00:00
2011-07-07 18:49:57 -04:00
2011-07-06 02:31:34 -04:00
#If they don't specify a color, use hashvalue
if ((client_color == "") and (client_set == "")):
client_set = colors[r.hasharray[0] % len(colors) ]
2011-07-06 01:41:06 -04:00
2011-07-05 19:31:17 -04:00
2011-08-30 16:35:59 -04:00
2011-07-05 19:31:17 -04:00
self.set_header("Content-Type", "image/" + ext)
2011-07-06 01:41:06 -04:00
hashlist = r.getHashList(client_set)
2011-08-08 20:02:33 +00:00
#OK, here's where we do some creative sorting.
#Basically, we have two integers before every file
#The first one ensure FS order, which is necessary to match the RH.org server
#The second one ensures build order.
#The FS order is only necessary during picking elements. Now, we want the second sort
#So create a new list, ordered by the second integer
hlcopy = []
for element in hashlist:
element = element[0:element.find("/",element.find("#") -4) +1] + element[element.find("#") +1:len(element)]
hlcopy.append(element)
#Now, combine them into tuples, and sort. A tuples list always sorts by the FIRST element.
duality = zip(hlcopy,hashlist)
duality.sort()
pprint.pprint(duality)
hlcopy,hashlist = zip(*duality)
pprint.pprint(hlcopy)
print "------"
pprint.pprint(hashlist)
2011-07-05 15:42:12 -04:00
robohash = Image.open(hashlist[0])
2011-07-07 18:49:57 -04:00
robohash = robohash.resize((1024,1024))
2011-07-05 15:42:12 -04:00
for png in hashlist:
img = Image.open(png)
2011-07-07 18:49:57 -04:00
img = img.resize((1024,1024))
2011-07-05 15:42:12 -04:00
robohash.paste(img,(0,0),img)
2011-07-05 21:09:08 -04:00
if ext == 'bmp':
#Flatten bmps
r, g, b, a = robohash.split()
robohash = Image.merge("RGB", (r, g, b))
2011-07-07 18:49:57 -04:00
if client_bgset is not "":
bglist = []
2012-04-03 12:45:23 -04:00
backgrounds = os.listdir(client_bgset)
backgrounds.sort()
for ls in backgrounds:
2011-07-07 18:49:57 -04:00
if not ls.startswith("."):
bglist.append(client_bgset + "/" + ls)
bg = Image.open(bglist[r.hasharray[3] % len(bglist)])
bg = bg.resize((1024,1024))
bg.paste(robohash,(0,0),robohash)
robohash = bg
2011-07-08 18:45:01 +00:00
robohash = robohash.resize((sizex,sizey),Image.ANTIALIAS)
2012-07-26 04:56:31 -04:00
if ext != 'datauri':
robohash.save(self,format=ext)
else:
fakefile = cStringIO.StringIO()
robohash.save(fakefile,format='jpeg')
fakefile.seek(0)
data_uri = fakefile.read().encode("base64").replace("\n", "")
2012-07-26 05:16:07 -04:00
self.write("data:image/jpeg;base64," + data_uri)
2012-07-26 04:56:31 -04:00
2011-07-05 15:42:12 -04:00
2011-07-05 19:31:17 -04:00
2011-07-05 15:42:12 -04:00
2011-07-06 06:39:35 +00:00
def main():
tornado.options.parse_command_line()
# timeout in seconds
timeout = 10
socket.setdefaulttimeout(timeout)
settings = {
"static_path": os.path.join(os.path.dirname(__file__), "static"),
"cookie_secret": "9b90a85cfe46cad5ec136ee44a3fa332",
"login_url": "/login",
"xsrf_cookies": True,
}
application = tornado.web.Application([
2012-09-16 22:17:57 -04:00
(r'/(crossdomain\.xml)', tornado.web.StaticFileHandler, {"path": os.path.join(os.path.dirname(__file__),
"static/")}),
2011-07-06 06:39:35 +00:00
(r"/static/(.*)", tornado.web.StaticFileHandler, {"path": os.path.join(os.path.dirname(__file__),
"static/")}),
(r"/", MainHandler),
(r"/(.*)", ImgHandler),
], **settings)
2011-07-06 18:14:09 +00:00
http_server = tornado.httpserver.HTTPServer(application,xheaders=True)
2011-07-06 06:39:35 +00:00
http_server.listen(options.port)
2011-07-05 15:42:12 -04:00
tornado.ioloop.IOLoop.instance().start()
2011-07-06 06:39:35 +00:00
if __name__ == "__main__":
main()