Skip to content

Instantly share code, notes, and snippets.

@arpanpal010
Created February 4, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save arpanpal010/6ed939b81764c264338c to your computer and use it in GitHub Desktop.
Save arpanpal010/6ed939b81764c264338c to your computer and use it in GitHub Desktop.
minimal text based bulletin board using http.server, single threaded, auto refreshes. exactly 100 loc.
from __future__ import print_function #from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
import http.server, urllib, datetime
#=================================================================
sUrl="/chatbox" #server url
port=8080 #server port
timedRefresh="15" #time before page refreshes
msgBox=[] #messages held here as dict objects
#=================================================================
# create html
#=================================================================
def makeHtml():
msgHtml="" #html from msgbox
for item in msgBox:
msgHtml+= "<div><b class='alias'>" + item['alias'] + "</b>: <span class='timestamp'>" + str(item['created']).split(".")[0] +"</span><p class='message'>" + item['message'] + "</p></div>"
#html to render in page
htmlIndex="""<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Chatbox!</title>
<!--meta http-equiv="refresh" content="10"/-->
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<style>
@import url(http://fonts.googleapis.com/css?family=Open+Sans:300,400);
body{ font-family: "Open Sans", sans; font-weight: 300; font-size: 15px; padding: 0 2em; max-width: 960px; margin: 0 auto;}
h1 { font-weight: 300; text-align: center;}
textarea {overflow: auto; resize: vertical; margin-top: 0.5em; display: block; width: 100%;}
#form-wrapper {padding: 0;}
#update-wrapper {padding: 0.3em 0;}
#messages-wrapper {padding: 1em 0;}
#messages-wrapper div { border-bottom: 1px solid #F5F5F5; padding: 0.5em;}
#messages-wrapper div .alias {font-weight: 400; display: inline; border-bottom: 1px solid #9E9E9E;}
#messages-wrapper div .message { display: inline-block; word-wrap: break-word; padding: 2emi 0;}
#messages-wrapper div .timestamp { display: inline-block; float: right; margin-top: 0em;}
</style>
</head>
<body>
<h1 style="margin-bottom: 0;"><a href='""" + sUrl + """' style="color: #39c; text-decoration: none;">Chatbox!</a></h1>
<p style="text-align: center; margin: 0;">Anonymous text board for small groups.</p>
<div id="form-wrapper">
<div id="update-wrapper">
<input type="checkbox" id="updateCheck" checked/>
<span id="countdown"></span>
</div>
<form method="post" action="">
<input type="text" name="alias" placeholder="alias(optional)" style="display: block; width: 100%;"/>
<textarea name="message" placeholder="message" autofocus required></textarea>
<button type="submit">Submit</button>
</form>
</div>
<div id="messages-wrapper"> """ + msgHtml + """ </div>
<!--auto refresh with js + counter-->
<script>(function countdown(remaining) {
if (document.getElementById('updateCheck').checked != false) { //if remaining zero, reload page
if(remaining <= 0)
location.reload(true);
document.getElementById('countdown').innerHTML = "Updating in: " + remaining;
setTimeout(function(){ countdown(remaining - 1); }, 1000);
} else { //check status in a bit
document.getElementById('countdown').innerHTML = "Check to autoupdate.";
setTimeout(function(){countdown(remaining);}, 2000);
} })(""" + timedRefresh + """); // seconds
</script>
</body>
</html> """
return htmlIndex
#=================================================================
# request handler
#=================================================================
class ChatHandler(http.server.BaseHTTPRequestHandler): #handler here
def do_GET(self): #show form and messages
html=makeHtml()
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.send_header('Content-length', len(html))
self.end_headers()
self.wfile.write(bytes(html, 'utf-8'))
return
def do_POST(self): #add message to list, redirect to base page
l=int(self.headers['Content-length'])
pdata=urllib.parse.parse_qs(self.rfile.read(l).decode('utf-8'))
if pdata:
alias="".join(pdata.get('alias', "anonymous")) #sometimes returning list
message="".join(pdata.get('message')) # message required to do post
if message:
global msgBox
msgBox.append({'alias':alias, 'message': message, 'created': datetime.datetime.now()})
self.send_response(302)
self.send_header("Location", sUrl) #redirect
self.end_headers()
return
#=================================================================
# run server
#=================================================================
print("Server running on port: ", port)
httpd=http.server.HTTPServer(("", port), ChatHandler)
try: httpd.serve_forever()
except KeyboardInterrupt:
print("Shutting down server");
httpd.socket.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment