diff --git a/examples/guestbook.py b/examples/guestbook.py index c3cb1d8..7e4d945 100644 --- a/examples/guestbook.py +++ b/examples/guestbook.py @@ -1,60 +1,63 @@ """ -A guestbook application that accepts input from guests and stores messages in -a simple text file. +A simple guestbook application that accepts and displays text messages. + +This is an example of how to return a 10 INPUT request to the client and +retrieve their response by parsing the URL query string. This example stores +the guestbook inside of a persistent sqlite database. """ -import asyncio -import pathlib + +import sqlite3 from datetime import datetime -import jetforce -from jetforce import Response, Status +from jetforce import GeminiServer, JetforceApplication, Response, Status -guestbook = pathlib.Path("guestbook.txt") +DB = "/tmp/guestbook.sqlite" + +SCHEMA = """ +CREATE TABLE IF NOT EXISTS guestbook ( + ip_address TEXT, + created_at timestamp, + message TEXT +) +""" +with sqlite3.connect(DB) as c: + c.execute(SCHEMA) -app = jetforce.JetforceApplication() +app = JetforceApplication() @app.route("", strict_trailing_slash=False) def index(request): - data = ["Guestbook", "=>/submit Sign the Guestbook", ""] + lines = ["Guestbook", "=>/submit Sign the Guestbook"] - guestbook.touch(exist_ok=True) - with guestbook.open("r") as fp: - for line in fp: - line = line.strip() - if line.startswith("=>"): - data.append(line[2:]) - else: - data.append(line) + with sqlite3.connect(DB, detect_types=sqlite3.PARSE_DECLTYPES) as c: + for row in c.execute("SELECT * FROM guestbook ORDER BY created_at"): + ip_address, created_at, message = row + line = f"{created_at:%Y-%m-%d} - [{ip_address}] {message}" + lines.append("") + lines.append(line) - data.extend(["", "...", ""]) - return Response(Status.SUCCESS, "text/gemini", "\n".join(data)) + lines.extend(["", "...", ""]) + body = "\n".join(lines) + + return Response(Status.SUCCESS, "text/gemini", body) @app.route("/submit") def submit(request): if request.query: message = request.query[:256] - created = datetime.utcnow() - with guestbook.open("a") as fp: - fp.write(f"\n[{created:%Y-%m-%d %I:%M %p}]\n{message}\n") - + created = datetime.now() + ip_address = request.environ["REMOTE_HOST"] + with sqlite3.connect(DB) as c: + values = (ip_address, created, message) + c.execute("INSERT INTO guestbook VALUES (?, ?, ?)", values) return Response(Status.REDIRECT_TEMPORARY, "") else: return Response(Status.INPUT, "Enter your message (max 256 characters)") if __name__ == "__main__": - args = jetforce.command_line_parser().parse_args() - ssl_context = jetforce.make_ssl_context( - args.hostname, args.certfile, args.keyfile, args.cafile, args.capath - ) - server = jetforce.GeminiServer( - host=args.host, - port=args.port, - ssl_context=ssl_context, - hostname=args.hostname, - app=app, - ) - asyncio.run(server.run()) + server = GeminiServer(app) + server.run()