|
@@ -6,15 +6,15 @@
|
|
|
from io import BufferedReader
|
|
|
import os
|
|
|
from threading import Thread
|
|
|
+from typing import Union
|
|
|
from bottle import (
|
|
|
route, request, response,
|
|
|
redirect, abort,
|
|
|
template, static_file,
|
|
|
- FormsDict, HTTPError, HTTPResponse,
|
|
|
+ FormsDict, HTTPError,
|
|
|
)
|
|
|
-from psycopg import connect
|
|
|
-
|
|
|
-from app.data.filter import get_filter, get_query_param
|
|
|
+from psycopg import Cursor, connect
|
|
|
+from psycopg.rows import TupleRow
|
|
|
|
|
|
from .hash_util import blake, bytes_to_base32, hash_to_base32, hex_to_hash, normalize_base32
|
|
|
from .route_decorators import normalize, normalize_query, poison, cursor
|
|
@@ -31,74 +31,63 @@ if not password.split('=',1)[1]:
|
|
|
password = ''
|
|
|
conn = connect(f"{host} {db} {user} {password}")
|
|
|
|
|
|
-CACHE = Cache(10)
|
|
|
-
|
|
|
@route('/grocery/static/<filename:path>')
|
|
|
def send_static(filename):
|
|
|
return static_file(filename, root='app/rest/static')
|
|
|
|
|
|
|
|
|
@route('/grocery/trend', method=['GET', 'POST'])
|
|
|
-@poison(cache=CACHE)
|
|
|
+@poison(cache=Cache(10))
|
|
|
@normalize
|
|
|
-def trend():
|
|
|
- key = normalize_query(request.params)
|
|
|
- parts = key.split('=')
|
|
|
- if len(parts) == 2 and parts[0] == 'hash':
|
|
|
- _, _hash = parts
|
|
|
- key = hex_to_hash(_hash)
|
|
|
-
|
|
|
- page = CACHE[key]
|
|
|
-
|
|
|
- _, _, path, *_ = request.urlparts
|
|
|
+def trend(key: str, forms: FormsDict, cache: Cache):
|
|
|
+ page = cache[key]
|
|
|
if page:
|
|
|
return page
|
|
|
|
|
|
- param = get_filter(request.params, allow=PARAMS)
|
|
|
- params = FormsDict({
|
|
|
- k: get_query_param(*param[k]) if k != 'organic' else BOOLEAN[
|
|
|
- BOOLEAN.get(request.params.organic, None)
|
|
|
- ] for k in sorted(param) if param[k]
|
|
|
- })
|
|
|
-
|
|
|
- return CACHE.add(key, CachedLoadingPage(
|
|
|
+ _, _, path, *_ = request.urlparts
|
|
|
+
|
|
|
+ return cache.add(key, CachedLoadingPage(
|
|
|
template("loading", progress=[]),
|
|
|
lambda queue: Thread(target=worker.trend, args=(
|
|
|
- queue, conn, path, params
|
|
|
+ queue, conn, path, forms
|
|
|
)).start()
|
|
|
))
|
|
|
|
|
|
|
|
|
@route('/grocery/groups', method=['GET', 'POST'])
|
|
|
+@poison(cache=Cache(10))
|
|
|
@normalize
|
|
|
@cursor(connection=conn)
|
|
|
-def groups(cur):
|
|
|
+def groups(cur: Cursor[TupleRow], key: Union[int, str], forms: FormsDict, cache: Cache):
|
|
|
response.content_type = 'application/xhtml+xml; charset=utf-8'
|
|
|
- return get_groups(cur, request.query)
|
|
|
+ return get_groups(cur, forms)
|
|
|
|
|
|
|
|
|
@route('/grocery/categories', method=['GET', 'POST'])
|
|
|
+@poison(cache=Cache(10))
|
|
|
@normalize
|
|
|
@cursor(connection=conn)
|
|
|
-def categories(cur):
|
|
|
+def categories(cur: Cursor[TupleRow], key: Union[int, str], forms: FormsDict, cache: Cache):
|
|
|
response.content_type = 'application/xhtml+xml; charset=utf-8'
|
|
|
- return get_categories(cur, request.query)
|
|
|
+ return get_categories(cur, forms)
|
|
|
|
|
|
|
|
|
@route('/grocery/products', method=['GET', 'POST'])
|
|
|
+@poison(cache=Cache(10))
|
|
|
@normalize
|
|
|
@cursor(connection=conn)
|
|
|
-def products(cur):
|
|
|
+def products(cur: Cursor[TupleRow], key: Union[int, str], forms: FormsDict, cache: Cache):
|
|
|
response.content_type = 'application/xhtml+xml; charset=utf-8'
|
|
|
- return get_products(cur, request.query)
|
|
|
+ return get_products(cur, forms)
|
|
|
|
|
|
|
|
|
@route('/grocery/tags', method=['GET', 'POST'])
|
|
|
+@poison(cache=Cache(10))
|
|
|
@normalize
|
|
|
@cursor(connection=conn)
|
|
|
-def tags(cur):
|
|
|
+def tags(cur: Cursor[TupleRow], key: Union[int, str], forms: FormsDict, cache: Cache):
|
|
|
response.content_type = 'application/xhtml+xml; charset=utf-8'
|
|
|
- return get_tags(cur, request.query)
|
|
|
+ return get_tags(cur, forms)
|
|
|
|
|
|
CLIP_SIZE_LIMIT = 65535
|
|
|
SCHEME = "http://"
|