mirror of
https://github.com/patrickbeane/quote-of-the-day.git
synced 2026-01-27 18:30:25 +00:00
Secure, rate‑limited Flask + Gunicorn microservice with SQLite persistence, delivery tracking, and systemd deployment config. Includes setup script, HTML template, and production‑ready README.
65 lines
2.0 KiB
Python
65 lines
2.0 KiB
Python
from flask import Flask, jsonify, render_template
|
|
from flask_limiter import Limiter
|
|
from flask_limiter.util import get_remote_address
|
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
|
import sqlite3
|
|
import random
|
|
import os
|
|
|
|
app = Flask(__name__)
|
|
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1)
|
|
limiter = Limiter(key_func=get_remote_address, default_limits=["50/hour"])
|
|
limiter.init_app(app)
|
|
random.seed()
|
|
|
|
DB_FILE = "quotes.db"
|
|
|
|
def verify_db():
|
|
if not os.path.exists(DB_FILE):
|
|
raise RuntimeError("quotes.db not found. Run add-quotes.py to initialize.")
|
|
|
|
def get_random_quote():
|
|
"""Fetch a random quote from the database and increment delivered count"""
|
|
conn = sqlite3.connect(DB_FILE)
|
|
c = conn.cursor()
|
|
|
|
# Pick a random quote ID
|
|
c.execute("SELECT id, quote, author, delivered FROM quotes ORDER BY RANDOM() LIMIT 1")
|
|
row = c.fetchone()
|
|
if not row:
|
|
conn.close()
|
|
return None
|
|
|
|
quote_id, quote_text, author, delivered = row
|
|
|
|
# Increment delivered count atomically
|
|
c.execute("UPDATE quotes SET delivered = delivered + 1 WHERE id = ?", (quote_id,))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
return {"id": quote_id, "quote": quote_text, "author": author, "delivered": delivered + 1}
|
|
|
|
@app.route("/")
|
|
def main():
|
|
return render_template("quotes.html")
|
|
|
|
@app.route("/quote")
|
|
@limiter.limit("20/minute")
|
|
def quote():
|
|
quote = get_random_quote()
|
|
if not quote:
|
|
return "No quotes found in database!", 500
|
|
return f"{quote['quote']} - {quote['author']}"
|
|
|
|
@app.route("/api/quote")
|
|
@limiter.limit("50/minute")
|
|
def quote_api():
|
|
quote = get_random_quote()
|
|
if not quote:
|
|
return jsonify({"error": "No quotes found"}), 500
|
|
return jsonify(quote)
|
|
|
|
if __name__ == "__main__":
|
|
verify_db()
|
|
"""Running on Oracle's private network, in my instance - here it is 0.0.0.0 so only one node is needed"""
|
|
app.run(host="0.0.0.0", port=5051, debug=True) |