スキップしてメイン コンテンツに移動

Android端末をサーバにしてHTML5を使ったお絵かきBBSを作成する

最近、HTML5に触れる機会があり、その良さが何となく伝わってきたので、何かしら簡単なコードを書いてみたくなった。そこで、ちっちゃいけどリッチ、というギャップを楽しむためにAndroid端末を使うことにした。具体的には、Android端末をSL4Aウェブサーバにして、HTML5をインターフェイスにしたお絵かきBBSをPythonで書いてみた。

BBSでは絵とテキストを扱うことができて、それらはAndroid端末上でSQLiteのデータベースで管理される。利用者の利便を考えて、名前などはクッキーで保存する。3G回線や無線LANなどで接続することを考慮して、IPアドレスも取得できるようにした。また、書き込み時にサーバのAndroid端末が振動して書き込みがあったことを知らせてくれる。因みに、NTTドコモの3G回線で使うためには、グローバルIPが振られるmopera Uなどのサービスが必要で、spモードでは利用できない。

実際に作ってみたプログラムのスクリーンショットを冒頭に入れてみた。必要最低限の機能しかないが、それでも文章と画像を保存できるちゃんとした掲示板だ。草の根BBSのころを考えると隔世の感がある。

以下に今回作成したソースコードを載せておく。こんな短いコードでもちゃんと機能するのが不思議な感じだ。

image_bbs.py

# -*- coding: utf-8 -*- import sys,os,cgi,sqlite3,datetime import socket,fcntl from wsgiref.simple_server import make_server import android droid=android.Android() LIMIT=10 # 最大表示記事数. DB_FILE='/sdcard/image_bbs.sqlite' P=8080 con=sqlite3.connect(DB_FILE) cur=con.cursor() cur.execute('CREATE TABLE IF NOT EXISTS bbs (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, user TEXT, datetime TEXT, image TEXT, text TEXT)') INSERT_DB='INSERT INTO bbs VALUES(NULL,?,?,?,?)' def ipconfig(): s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) s.connect(('gmail.com',80)) return s.getsockname()[0] def post(user,image,text): if image=='' or text=='': return if user=='': user='匿名' dt=datetime.datetime.today().strftime('%Y-%m-%d %H:%M:%S') cur.execute(INSERT_DB,(cgi.escape(user.decode('utf-8')),dt,cgi.escape(image.decode('utf-8')).replace('\n','<br />'),cgi.escape(text.decode('utf-8')).replace('\n','<br />'))) con.commit() droid.vibrate() #droid.notify(user,text) def bbs(environ,start_response): global IP if environ['PATH_INFO']=='/': user='' if environ.has_key('HTTP_COOKIE'): cookie={} for d in environ['HTTP_COOKIE'].strip(';').split(';'): d=d.split('=') cookie[d[0]]=d[1] if cookie.has_key('BBSUSER'): user=cookie['BBSUSER'] if environ['REQUEST_METHOD']=='POST': fs=cgi.FieldStorage(fp=environ['wsgi.input'],environ=environ,keep_blank_values=1) user=fs.getfirst('user','').strip() image=fs.getfirst('bbsImage','') text=fs.getfirst('text','').strip() post(user,image,text) data=u"""<!DOCTYPE html> <html><head> <meta http-equiv="Set-Cookie" content="BBSUSER=%s"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Image BBS by Android</title></head><body> <p><a href="http://%s:%d">http://%s:%d</a></p> <form action="/" method="post" id="form"> <span>名前:<input type="text" name="user" size="20" maxlength="30" value="%s" /></span> <div><canvas id="bbsCanvas" width="400" height="200" style="border:1px solid;"></canvas></div> <textarea name="text" cols="40" rows="5"></textarea><br /> <input type="hidden" name="bbsImage" id="bbsImage" /> <span><input type="button" onclick="clearCanvas();" value="画像消去" /></span> <span><input type="button" value="更新" onclick="location.reload(true);" /></span> <span><input type="button" value="送信" onclick="setImage();this.form.submit();" /></span> </form> <script type="text/javascript"> var mouseDownFlag = false; window.onload = function() { draw(); setImage(); }; function draw() { var canvas = document.getElementById('bbsCanvas'); if (!canvas || !canvas.getContext) return false; var ctx = canvas.getContext('2d'); canvas.onmousemove = function(e) { if (mouseDownFlag) { var rect = e.target.getBoundingClientRect(); ctx.beginPath(); ctx.arc(e.clientX - rect.left, e.clientY - rect.top, 3, 0, Math.PI * 2, false); ctx.fill(); } } canvas.onmousedown = function(e) { mouseDownFlag = true; } canvas.onmouseup = function(e) { mouseDownFlag = false; } canvas.onmouseout = function(e) { mouseDownFlag = false; } } function setImage() { var canvas = document.getElementById('bbsCanvas'); if (!canvas || !canvas.getContext) return false; document.getElementById("bbsImage").value = canvas.toDataURL(); } function clearCanvas() { var canvas = document.getElementById('bbsCanvas'); if (!canvas || !canvas.getContext) return false; var ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, 400, 200); setImage(); } </script>""" % (user,IP,P,IP,P,user) cur.execute('SELECT * FROM bbs ORDER BY id DESC') for i, row in enumerate(cur): if i>=LIMIT: break data+=('<div><p>%d <b>%s</b> %s</p><img src="%s" alt="Image" width="400" height="200" style="border:1px solid;" /><p>%s</p></div>' % row) data+='</body></html>' start_response('200 OK',[('Content-type','text/html;charset=utf-8')]) return [data.encode('utf-8')] IP=ipconfig() httpd=make_server('',P,bbs) httpd.serve_forever()

コメント

wasabi さんの投稿…
詳しく教えてくれてありがとうございます。すごいですね。
http://www.coolmuster.jp/
nailayarber さんの投稿…
Slots - DrmCD
Free 남양주 출장안마 Slots. The more you buy slots, the more you get to win! Slots. If 인천광역 출장안마 you love 용인 출장안마 playing slots, you may 보령 출장샵 be a fan of free slots games! With over 200 different free 대전광역 출장샵 casino slots,