Skip to content

Instantly share code, notes, and snippets.

@vgel
Created July 23, 2012 12:47
Show Gist options
  • Save vgel/3163459 to your computer and use it in GitHub Desktop.
Save vgel/3163459 to your computer and use it in GitHub Desktop.
A simple message-board-type site in golfed python. Expanded version below if you can't read golfed code or want comments.
import BaseHTTPServer as b,sys,os,json,urlparse
p=(json.loads(open(sys.argv[1]).read()) if os.path.exists(sys.argv[1]) else {})
n="<br/>"
h="""<form action=%s method="post">Post: <textarea name="a"></textarea><input type="submit" value="Post!"/></form>"""
y=lambda s:urlparse.parse_qs(s)['a'][0]
class F(b.BaseHTTPRequestHandler):
def do_GET(s):
s.send_response(200)
s.send_header("Content-type","text/html")
s.end_headers()
if s.path=="/":
s.wfile.write(reduce(lambda m,x:m+"<a href="+x+">"+p[x][0]+"</a>"+n*2,sorted(p),"")+n+h%"n")
elif s.path in p:
s.wfile.write(reduce(lambda m,x:m+x+n*2,p[s.path],"<a href=\"/\">Back to top</a>"+n*2)+n+h%s.path[1:])
else:
s.send_error(404)
def do_POST(s):
s.send_response(301)
if s.path=="/n":
a="/"+str(len(p))
p[a]=[s.client_address[0]+" posted "+y(s.rfile.read(int(s.headers.getheader('content-length'))))]
s.send_header("Location",a)
elif s.path in p:
p[s.path].append(s.client_address[0]+" replied "+y(s.rfile.read(int(s.headers.getheader('content-length')))))
s.send_header("Location",s.path)
s.end_headers()
try:
b.HTTPServer(("", 8080), F).serve_forever()
finally:
open(sys.argv[1],'w').write(json.dumps(p))
import BaseHTTPServer, sys, os, json, urlparse
posts = {} #yes I should use an actual database.
if os.path.exists(sys.argv[1]): #we could remove this if you had to `touch` the file before running for the first time, but that would be dumb
posts = json.loads(open(sys.argv[1]).read())
newline="<br/>"
html_template="""
<form action=%s method="post">
Post: <textarea name="post"></textarea>
input type="submit" value="Post!"/>
</form>
"""
def get_POST_content(name, encoded): #this allows you to extract paramaters from form-encoded paramaters, such as `a=foo&b=bar&c=baz`. The [0] is because a 1-element list is returned for some reason.
return urlparse.parse_qs(encoded)[name][0]
class MessageBoardRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self): #handle GET
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
#These loops look a lot different. They are the reduce calls in the golfed code.
if self.path == "/":
message = ''
for post in sorted(posts):
message += "<a href=%s>" % post + posts[post][0] + "</a>" + newline*2 #newline*2 == newline+newline == <br/><br/>, if you aren't familiar with python.
post_new_thread = html_template % "n" #use the submit form, with the action as /n - create a new post
self.wfile.write(message + newline + post_new_thread) #write the OP posts and the submission box
elif self.path in posts:
message = "<a href=\"/\">Back to top</a>" + newline*2
for post in posts[self.path]:
message += post + newline*2
reply_to_thread = html_template % self.path[1:] #strip "/"
self.wfile.write(message + newline + reply_to_thread)
else:
self.send_error(404)
def do_POST(self): #handle POST
self.send_response(301) #301 is a redirect - we create their post and the redirect them to do_GET to actually render the page.
if self.path == "/n": #creating a new post - generate an id and create a post in `posts`
post_url = "/" + str(len(posts)) #/0, /1, etc. len(posts) is a cheap way to always get a unique id. Could lead to 4chan-style gets if this was ever actually used.
poster_ip = self.client_address[0] #Challenge: add tripcodes or even actual accounts instead of using ips.
posts[post_url] = [poster_ip + " posted " + get_POST_content('post', self.rfile.read(int(self.headers.getheader('content-length'))))]
self.send_header("Location", post_url)
elif self.path in posts: #replying to an existing post - append to the list
poster_ip = self.client_address[0]
posts[self.path].append(poster_ip + " replied " + get_POST_content('post', self.rfile.read(int(self.headers.getheader('content-length')))))
self.send_header("Location", self.path)
self.end_headers()
try:
BaseHTTPServer.HTTPServer(("", 8080), MessageBoardRequestHandler).serve_forever() # ("",8080) is localhost:8080.
finally:
open(sys.argv[1], 'w').write(json.dumps(posts)) #try and save posts. I'm not sure if you need 'w' or 'wb' for Windows, could someone test if it works?
# I don't think json cares if newlines are \n or \r\n, and not having b saves a byte.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment