refactor error handling, create voting macro
This commit is contained in:
parent
21a8681d2d
commit
89401a7189
56
app.py
56
app.py
@ -5,7 +5,7 @@ import sqlite3, random
|
||||
from flask import *
|
||||
from pagination import Pagination
|
||||
|
||||
PER_PAGE = 10
|
||||
PER_PAGE = 15
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@ -50,38 +50,38 @@ app.jinja_env.globals["url_for_other_page"] = url_for_other_page
|
||||
|
||||
|
||||
def get_post(id=1):
|
||||
row = query_db("SELECT * FROM QUOTES WHERE ID=?", (id,))
|
||||
row = query_db("SELECT * FROM quotes WHERE ID = ?", (id,))
|
||||
if not row:
|
||||
return False, []
|
||||
return True, row[0]
|
||||
|
||||
|
||||
def get_random_post():
|
||||
return query_db("SELECT * FROM QUOTES ORDER BY RANDOM() LIMIT 1", one=True)
|
||||
return query_db("SELECT * FROM quotes ORDER BY RANDOM() LIMIT 1", one=True)
|
||||
|
||||
|
||||
def get_next_post_id():
|
||||
return query_db("SELECT MAX(ID) FROM QUOTES", one=True)[0] + 1
|
||||
return query_db("SELECT MAX(id) FROM quotes", one=True)[0] + 1
|
||||
|
||||
|
||||
def insert_new_post(id, text):
|
||||
query_db("INSERT INTO QUOTES VALUES (?,?,?)", (id, text, 0))
|
||||
query_db("INSERT INTO quotes VALUES (?, ?, ?)", (id, text, 0))
|
||||
get_db().commit()
|
||||
|
||||
|
||||
def vote(id, d=1):
|
||||
query_db("UPDATE QUOTES SET SCORE=SCORE+? WHERE ID=?", (d, id))
|
||||
query_db("UPDATE quotes SET score = score + ? WHERE id = ?", (d, id))
|
||||
get_db().commit()
|
||||
|
||||
|
||||
def count_all_quotes():
|
||||
return query_db("SELECT COUNT(*) FROM QUOTES", one=True)[0]
|
||||
return query_db("SELECT COUNT(*) FROM quotes", one=True)[0]
|
||||
|
||||
|
||||
def get_quotes_for_page(page):
|
||||
offset = count_all_quotes() - ((page - 1) * PER_PAGE) + 1
|
||||
return query_db(
|
||||
"SELECT * FROM QUOTES WHERE ID < ? ORDER BY ID DESC LIMIT ?", (offset, PER_PAGE)
|
||||
"SELECT * FROM quotes WHERE id < ? ORDER BY id DESC LIMIT ?", (offset, PER_PAGE)
|
||||
)
|
||||
|
||||
|
||||
@ -89,9 +89,9 @@ def get_top_quotes_for_page(page):
|
||||
offset = (page - 1) * PER_PAGE
|
||||
return query_db(
|
||||
"""
|
||||
SELECT * FROM QUOTES WHERE ID NOT IN
|
||||
(SELECT ID FROM QUOTES ORDER BY SCORE DESC, ID DESC LIMIT ?)
|
||||
ORDER BY SCORE DESC, ID DESC LIMIT ?
|
||||
SELECT * FROM quotes WHERE id NOT IN
|
||||
(SELECT id FROM quotes ORDER BY score DESC, id DESC LIMIT ?)
|
||||
ORDER BY score DESC, id DESC LIMIT ?
|
||||
""",
|
||||
(offset, PER_PAGE),
|
||||
)
|
||||
@ -114,24 +114,26 @@ def search_quotes_db(searchterm):
|
||||
@app.route("/", defaults={"page": 1})
|
||||
@app.route("/page/<int:page>")
|
||||
def home(page):
|
||||
count = count_all_quotes()
|
||||
quotes = get_quotes_for_page(page)
|
||||
if not quotes and page != 1:
|
||||
abort(404)
|
||||
return render_template("oops.html", page=page)
|
||||
return render_template(
|
||||
"index.html", pagination=Pagination(page, PER_PAGE, count), quotes=quotes
|
||||
"index.html",
|
||||
pagination=Pagination(page, PER_PAGE, count_all_quotes()),
|
||||
quotes=quotes,
|
||||
)
|
||||
|
||||
|
||||
@app.route("/top", defaults={"page": 1})
|
||||
@app.route("/top/<int:page>")
|
||||
def top(page):
|
||||
count = count_all_quotes()
|
||||
quotes = get_top_quotes_for_page(page)
|
||||
if not quotes and page != 1:
|
||||
abort(404)
|
||||
return render_template("oops.html", page=page)
|
||||
return render_template(
|
||||
"top.html", pagination=Pagination(page, PER_PAGE, count), quotes=quotes
|
||||
"top.html",
|
||||
pagination=Pagination(page, PER_PAGE, count_all_quotes()),
|
||||
quotes=quotes,
|
||||
)
|
||||
|
||||
|
||||
@ -143,14 +145,20 @@ def quote(id):
|
||||
return render_template("quote.html", row=row)
|
||||
|
||||
|
||||
@app.route("/quote/<int:id>/upvote")
|
||||
@app.route("/upvote/<int:id>")
|
||||
def upvote(id):
|
||||
ok, row = get_post(id)
|
||||
if not ok:
|
||||
return render_template("oops.html", id=id)
|
||||
vote(id, 1)
|
||||
return redirect(url_for("quote", id=id), code=307)
|
||||
|
||||
|
||||
@app.route("/quote/<int:id>/downvote")
|
||||
@app.route("/downvote/<int:id>")
|
||||
def downvote(id):
|
||||
ok, row = get_post(id)
|
||||
if not ok:
|
||||
return render_template("oops.html", id=id)
|
||||
vote(id, -1)
|
||||
return redirect(url_for("quote", id=id), code=307)
|
||||
|
||||
@ -171,19 +179,13 @@ def submit():
|
||||
|
||||
|
||||
@app.route("/random")
|
||||
def randomquote():
|
||||
def random():
|
||||
return render_template("quote.html", row=get_random_post())
|
||||
|
||||
|
||||
@app.route("/search", methods=["GET", "POST"])
|
||||
def search():
|
||||
query = request.args.get("q")
|
||||
results = search_quotes_db(query)
|
||||
return render_template(
|
||||
"search-results.html", results=results, total=len(results), query=query
|
||||
"search-results.html", results=search_quotes_db(query), query=query
|
||||
)
|
||||
|
||||
|
||||
@app.route("/js/<path:path>")
|
||||
def send_js(path):
|
||||
return send_from_directory("js", path)
|
||||
|
BIN
static/favicon.png
Normal file
BIN
static/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
0
js/jquery.min.js → static/jquery.min.js
vendored
0
js/jquery.min.js → static/jquery.min.js
vendored
@ -6,9 +6,9 @@
|
||||
<title>{% block title %}~chat irc quote database{% endblock %}</title>
|
||||
<link rel="stylesheet" href="https://tilde.team/css/hacker.css">
|
||||
<style>
|
||||
pre { white-space: pre-wrap; }
|
||||
pre { white-space: pre-wrap; }
|
||||
</style>
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="https://tilde.team/favicon-96x96.png">
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="{{ url_for('static', filename='favicon.png') }}">
|
||||
</head>
|
||||
|
||||
<body style="padding-top: 70px;">
|
||||
@ -22,14 +22,14 @@ pre { white-space: pre-wrap; }
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/">~chat qdb</a>
|
||||
<a class="navbar-brand" href="{{ url_for('home') }}">~chat qdb</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="https://tilde.chat">< ~chat</a></li>
|
||||
<li><a href="/top">top</a></li>
|
||||
<li><a href="/random">random</a></li>
|
||||
<li><a href="/quote/submit">submit</a></li>
|
||||
<li><a href="https://tilde.chat/">< ~chat</a></li>
|
||||
<li><a href="{{ url_for('top') }}">top</a></li>
|
||||
<li><a href="{{ url_for('random') }}">random</a></li>
|
||||
<li><a href="{{ url_for('submitform') }}">submit</a></li>
|
||||
</ul>
|
||||
<form class="navbar-form navbar-right" action="{{ url_for('search') }}">
|
||||
<div class="form-group">
|
||||
@ -43,13 +43,13 @@ pre { white-space: pre-wrap; }
|
||||
<h1>{% block pagetitle %}~chat irc quote database{% endblock %}</h1>
|
||||
|
||||
{% block content %}
|
||||
<p>this is an irc quote database, in the style of <a href="http://bash.org">bash.org</a>, that aims to catalog moments on ~chat irc.</p>
|
||||
<p>this is an irc quote database, in the style of <a href="http://bash.org">bash.org</a>, that aims to catalog moments on tilde.chat.</p>
|
||||
{% endblock %}
|
||||
|
||||
</div>
|
||||
|
||||
<script src="/js/jquery.min.js"></script>
|
||||
<script src="/js/bootstrap.min.js"></script>
|
||||
<script src="{{ url_for('static', filename='jquery.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='bootstrap.min.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
{% extends 'base.html' %}
|
||||
{% import 'pagination.html' as pages %}
|
||||
{% import 'macros.html' as macros %}
|
||||
|
||||
{% block content %}
|
||||
{{ super() }}
|
||||
{{ pages.render(pagination) }}
|
||||
{{ macros.paginate(pagination) }}
|
||||
|
||||
{% for quote in quotes %}
|
||||
<hr>
|
||||
<pre>{{quote[1]}}</pre>
|
||||
<p>score: {{ quote[2] }} (<a href="/quote/{{quote[0]}}/upvote">upvote</a>/<a href="/quote/{{quote[0]}}/downvote">downvote</a>) (<a href="/quote/{{quote[0]}}">permalink</a>)</p>
|
||||
<pre>{{ quote['content'] }}</pre>
|
||||
<p>{{ macros.voting_buttons(quote['id'], quote['score']) }}</p>
|
||||
{% endfor %}
|
||||
|
||||
<hr>
|
||||
{{ pages.render(pagination) }}
|
||||
{{ macros.paginate(pagination) }}
|
||||
{% endblock %}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{% macro render(pagination) %}
|
||||
{% macro paginate(pagination) %}
|
||||
<div class="pagination">
|
||||
{% if pagination.has_prev %}
|
||||
<a href="{{ url_for_other_page(pagination.page - 1) }}">< prev</a>
|
||||
<a href="{{ url_for_other_page(pagination.page - 1) }}">←</a>
|
||||
{% endif %}
|
||||
|
||||
{%- for page in pagination.iter_pages() %}
|
||||
@ -12,12 +12,18 @@
|
||||
<strong>{{ page }}</strong>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="ellipsis"></span>
|
||||
<span class="ellipsis">…</span>
|
||||
{% endif %}
|
||||
{%- endfor %}
|
||||
|
||||
{% if pagination.has_next %}
|
||||
<a href="{{ url_for_other_page(pagination.page + 1) }}">next ></a>
|
||||
<a href="{{ url_for_other_page(pagination.page + 1) }}">→</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro voting_buttons(id, score) %}
|
||||
<a href="{{ url_for('quote', id=id) }}">{{ id }}</a>:
|
||||
score: {{ score }}
|
||||
<a href="{{ url_for('upvote', id=id) }}">↑</a>/<a href="{{ url_for('downvote', id=id) }}">↓</a>
|
||||
{% endmacro %}
|
@ -1,10 +1,13 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}~chat IRC quote database - big woops!{% endblock %}
|
||||
{% block title %}big woops! - ~chat IRC quote database{% endblock %}
|
||||
{% block pagetitle %}big woops!{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<p>I'm sorry, but something has gone terribly wrong. Please try again later!</p>
|
||||
{% if id %}
|
||||
<p>quote {{ id }} does not exist. <a href="/quote/submit">submit a new one?</a></p>
|
||||
<p>quote {{ id }} does not exist. <a href="{{ url_for('submit') }}">submit a new one?</a></p>
|
||||
{% endif %}
|
||||
{% if page %}
|
||||
<p>page {{ page }} does not exist. <a href="{{ url_for('home') }}">go back home</a></p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
@ -1,10 +1,10 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}~chat IRC quote database - quote {{ row[0] }}{% endblock %}
|
||||
{% block pagetitle %}quote {{ row[0] }}{% endblock %}
|
||||
{% block title %}quote {{ row['id'] }} - ~chat IRC quote database{% endblock %}
|
||||
{% block pagetitle %}quote {{ row['id'] }}{% endblock %}
|
||||
{% import 'macros.html' as macros %}
|
||||
|
||||
{% block content %}
|
||||
<p>score: {{ row[2] }}
|
||||
(<a href="/quote/{{row[0]}}/upvote">upvote</a>/<a href="/quote/{{row[0]}}/downvote">downvote</a>)
|
||||
</p>
|
||||
<pre>{{row[1]}}</pre>
|
||||
<pre>{{ row['content'] }}</pre>
|
||||
<p>{{ macros.voting_buttons(row['id'], row['score']) }}</p>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -1,14 +1,15 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}search results{% endblock%}
|
||||
{% block pagetitle %}search results{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<p>found {{ total }} results for <code>{{ query }}</code></p>
|
||||
<p>matches are indicated by square brackets</p>
|
||||
<p>found {{ results|length }} results for <code>{{ query }}</code></p>
|
||||
<p>matches are indicated by [square brackets]</p>
|
||||
{% for quote in results %}
|
||||
<hr>
|
||||
<p><a href="{{ url_for('quote', id=quote[0]) }}">{{ quote[0] }}</a></p>
|
||||
<pre>{{ quote[1] }}</pre>
|
||||
<p><a href="/quote/{{ quote[0] }}">permalink</a></p>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}~chat IRC quote database - submit a quote!{% endblock %}
|
||||
{% block title %}submit a quote! - ~chat quote database{% endblock %}
|
||||
{% block pagetitle %}submit a quote!{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<p>please check with the people whose logs you're submitting for consent to post.</p>
|
||||
<form action="/submit" method="POST">
|
||||
<form action="{{ url_for('submit') }}" method="POST">
|
||||
<p>quote:</p>
|
||||
<textarea class="form-control" name="quote" rows="8" cols="80"></textarea>
|
||||
<br>
|
||||
|
@ -1,17 +1,18 @@
|
||||
{% extends 'base.html' %}
|
||||
{% import 'pagination.html' as pages %}
|
||||
{% import 'macros.html' as macros %}
|
||||
|
||||
{% block title %}top quotes | ~chat qdb{% endblock %}
|
||||
{% block pagetitle %}top quotes of all time{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ pages.render(pagination) }}
|
||||
{{ macros.paginate(pagination) }}
|
||||
|
||||
{% for quote in quotes %}
|
||||
<hr>
|
||||
<pre>{{quote[1]}}</pre>
|
||||
<p>score: {{ quote[2] }} (<a href="/quote/{{quote[0]}}/upvote">upvote</a>/<a href="/quote/{{quote[0]}}/downvote">downvote</a>) (<a href="/quote/{{quote[0]}}">permalink</a>)</p>
|
||||
<pre>{{ quote['content'] }}</pre>
|
||||
<p>{{ macros.voting_buttons(quote['id'], quote['score']) }}</p>
|
||||
{% endfor %}
|
||||
|
||||
{{ pages.render(pagination) }}
|
||||
<hr>
|
||||
{{ macros.paginate(pagination) }}
|
||||
{% endblock %}
|
||||
|
Loading…
Reference in New Issue
Block a user