# HG changeset patch # User Nolan Prescott # Date 1499295458 14400 # Wed Jul 05 18:57:38 2017 -0400 # Node ID d23585cee1fc089ecd3bcc66aed12d549a2d7a47 # Parent 0000000000000000000000000000000000000000 Commit working implementation of async glue boy - could probably use a real 404, rather than the current behavior diff --git a/.gitignore b/.gitignore new file mode 100644 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.sqlite +__pycache__ +*.pyc +*.pid diff --git a/README.org b/README.org new file mode 100644 --- /dev/null +++ b/README.org @@ -0,0 +1,27 @@ +* What the fork? + This is a fork (of a fork) of the [[https://github.com/NPrescott/glue-boy][original glue-boy]], a stupidly simple + pastebin. This is an async implementation using ~SQLite~ rather than the + filesystem. + +** installation + this iteration of ~glue-boy~ is built on [[https://github.com/twisted/klein][Klein]] and Python 3.6 (for `async def` + and `f`-strings) + + #+BEGIN_EXAMPLE + pip install -r requirements.txt + #+END_EXAMPLE + + and then and you're off and running + + To initialize the database (required): + + #+BEGIN_EXAMPLE + sqlite3 glues.sqlite 7;" | sqlite3 glues.sqlite +echo "vacuum;" | sqlite3 glues.sqlite diff --git a/glue_boy.py b/glue_boy.py new file mode 100755 --- /dev/null +++ b/glue_boy.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +''' +A stupidly simple pastebin. + +requires current directory be on PYTHONPATH, e.g. + $ export PYTHONPATH=$(pwd) + $ twistd -n web --class=glue_boy.resource +''' + +import datetime +from uuid import uuid4 + +from klein import Klein +from twisted.enterprise import adbapi +from twisted.internet.defer import ensureDeferred +from twisted.web.static import File + + +class GluesDatabase(): + db_pool = adbapi.ConnectionPool('sqlite3', 'glues.sqlite', + check_same_thread=False) + table = 'glues' + + async def get_paste(self, paste_id): + ''' + Return a string from the database, if matching id is not found return the + empty string + ''' + await self.db_pool.runOperation("UPDATE glues SET last_accessed = ? " + "WHERE id = ?", + (datetime.datetime.now(), paste_id)) + content = await self.db_pool.runQuery("SELECT content FROM glues " + "WHERE id = ?", (paste_id,)) + if content: + return content[0][0] + return "" + + async def write_paste(self, content): + ''' + Write string content to the database, return the id it was written with. + ''' + paste_id = uuid4().hex[:6] + await self.db_pool.runOperation("INSERT INTO glues (id, content) VALUES (?, ?)", + (paste_id, content)) + return paste_id + + +class WebApp(): + app = Klein() + db = GluesDatabase() + + @app.route('/', methods=['GET', 'POST']) + def new_paste(self, request): + if request.method == b'GET': + # hack to get around: https://github.com/twisted/klein/issues/41 + f = File('./') + f.indexNames = ['index.html'] + return f + elif request.method == b'POST': + content, *_ = request.args[b'content'] + d = ensureDeferred(self.db.write_paste(content)) + d.addCallback( + lambda paste_id: request.redirect(f'./content/{paste_id}')) + return d + + @app.route('/content/', methods=['GET']) + def existing_paste(self, request, paste_id): + request.setHeader('Content-Type', 'text/plain') + return self.db.get_paste(paste_id) + +resource = WebApp().app.resource diff --git a/index.html b/index.html new file mode 100644 --- /dev/null +++ b/index.html @@ -0,0 +1,34 @@ + + + + glue-boy + + +
+
+ +

+ +

+
+

+ glue-boy is command line friendly, upload a file with: +

+ $ curl -L -F "content=<filename.extension" -w "%{url_effective}\n" http://glue.nprescott.com + +

+ +

or paste STDOUT:

+

+ $ fortune | curl -L -F "content=<-" -w "%{url_effective}\n" http://glue.nprescott.com +

+ glue-boy +

+
+ + diff --git a/schema.sql b/schema.sql new file mode 100644 --- /dev/null +++ b/schema.sql @@ -0,0 +1,7 @@ +DROP TABLE if EXISTS glues; + +CREATE TABLE glues ( + id STRING, + content TEXT, + last_accessed DATETIME DEFAULT (DATETIME('now')) +);