Created
July 23, 2012 12:47
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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