diff --git a/inquisitor/app.py b/inquisitor/app.py index 3137810..bf70692 100644 --- a/inquisitor/app.py +++ b/inquisitor/app.py @@ -1,6 +1,7 @@ # Standard library imports import datetime import logging +import traceback # Third party imports from flask import Flask, render_template, request, jsonify @@ -21,12 +22,12 @@ app = Flask(__name__) dungeon = dungeonlib.Dungeon("dungeon") -def list_filter(whitelist=None, blacklist=None): - if whitelist is not None: - return lambda item: any([tag in whitelist for tag in item['tags']]) - if blacklist is not None: - return lambda item: not any([tag in blacklist for tag in item['tags']]) - return lambda s: True +def make_query_link(text, wl, bl): + wlp = "only=" + ",".join(wl) + blp = "not=" + ",".join(bl) + params = [p for p in (wlp, blp) if not p.endswith("=")] + query = "?{}".format("&".join(params)) + return '{0}'.format(text, query) @app.template_filter("datetimeformat") def datetimeformat(value, formatstr="%Y-%m-%d %H:%M:%S"): @@ -38,21 +39,61 @@ def datetimeformat(value, formatstr="%Y-%m-%d %H:%M:%S"): @app.route("/") def root(): dungeon = dungeonlib.Dungeon("dungeon") - filter_lambda = list_filter( - whitelist=request.args.get('only'), - blacklist=request.args.get('not')) + + # Determine exclusion filters + filters = [] + wl_param = request.args.get('only') + wl = wl_param.split(",") if wl_param else [] + bl_param = request.args.get('not') + bl = bl_param.split(",") if bl_param else [] + if wl: + filters.append(lambda item: not any([tag in wl for tag in item['tags']])) + if bl: + filters.append(lambda item: any([tag in bl for tag in item['tags']])) + + # Get all active+filtered items and all active tags + total = 0 active_items = [] - for cell_name in dungeon: - cell = dungeon[cell_name] - for item_id in cell: + active_tags = set() + item_read_exceptions = [] + for cell in dungeon: + for item_id in dungeon[cell]: try: - item = cell[item_id] + item = dungeon[cell][item_id] except: - logger.error("Exception reading {}/{}".format(cell_name, item_id)) + msg = "Exception reading {}/{}".format(cell, item_id) + logger.error(msg) + item_read_exceptions.append(msg) + item_read_exceptions.append(traceback.format_exc()) continue - if item['active'] and filter_lambda(item): + if item['active']: + active_tags |= set(item['tags']) + total += 1 + if not any(map(lambda f: f(item), filters)): active_items.append(item) - logger.info("Found {} active items".format(len(active_items))) + logger.info("Returning {} of {} items".format(len(active_items), total)) + if item_read_exceptions: + read_ex = { + 'title': 'Read errors', + 'body': "
{}".format("\n\n".join(item_read_exceptions)), + 'created': None, + } + active_items = [read_ex] + active_items + + # Create the feed control item + wl_minus = [make_query_link("only - {}".format(tag), [t for t in wl if t != tag], bl) for tag in wl] + wl_plus = [make_query_link("only + {}".format(tag), wl + [tag], bl) for tag in active_tags if tag not in wl] + bl_minus = [make_query_link("not - {}".format(tag), wl, [t for t in bl if t != tag]) for tag in bl] + bl_plus = [make_query_link("not + {}".format(tag), wl, bl + [tag]) for tag in active_tags if tag not in bl] + body = "
{}".format("\n".join(wl_minus + wl_plus + bl_minus + bl_plus)) + + feed_control = { + 'title': 'Feed Control', + 'body': body, + 'created': None, + } + active_items = [feed_control] + active_items + return render_template("feed.html", items=active_items[:100]) diff --git a/inquisitor/resources/feed.css b/inquisitor/resources/feed.css index d76f799..0102814 100644 --- a/inquisitor/resources/feed.css +++ b/inquisitor/resources/feed.css @@ -36,4 +36,7 @@ summary:focus { .strikethru span, .strikethru p { text-decoration: line-through; color: rgba(0, 0, 0, 0.2); +} +pre { + white-space: pre-wrap; } \ No newline at end of file diff --git a/inquisitor/templates/feed.html b/inquisitor/templates/feed.html index deb2bc5..6796bd4 100644 --- a/inquisitor/templates/feed.html +++ b/inquisitor/templates/feed.html @@ -26,7 +26,9 @@ {% if items %} {% for item in items %}