From 6dd4da5cfbfa35953a576c31d435684f3ad64401 Mon Sep 17 00:00:00 2001 From: Mint <> Date: Wed, 30 Nov 2022 02:36:35 +0300 Subject: [PATCH] Major frontend & API rehaul --- api.py | 93 +++++++++++++++++++++++++++-------------- index.html | 119 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 148 insertions(+), 64 deletions(-) diff --git a/api.py b/api.py index 051fca7..f2742ed 100644 --- a/api.py +++ b/api.py @@ -6,6 +6,7 @@ from fastapi.templating import Jinja2Templates from requests import get from json import loads from re import sub +from datetime import datetime with open("config.json") as f: config = loads(f.read()) @@ -30,9 +31,33 @@ def info(): "blocks_recorded": blocks } +@app.get(base_url+"/top") +def top(blocked: int = None, blockers: int = None): + conn = sqlite3.connect("blocks.db") + c = conn.cursor() + if blocked == None and blockers == None: + raise HTTPException(status_code=400, detail="No filter specified") + elif blocked != None: + if blocked > 500: + raise HTTPException(status_code=400, detail="Too many results") + c.execute("select blocked, count(blocked) from blocks where block_level = 'reject' group by blocked order by count(blocked) desc limit ?", (blocked,)) + elif blockers != None: + if blockers > 500: + raise HTTPException(status_code=400, detail="Too many results") + c.execute("select blocker, count(blocker) from blocks where block_level = 'reject' group by blocker order by count(blocker) desc limit ?", (blockers,)) + scores = c.fetchall() + c.close() + + scoreboard = [] + print(scores) + for domain, highscore in scores: + scoreboard.append({"domain": domain, "highscore": highscore}) + + return scoreboard + @app.get(base_url+"/api") -def blocked(domain: str = None, reason: str = None): - if domain == None and reason == None: +def blocked(domain: str = None, reason: str = None, reverse: str = None): + if domain == None and reason == None and reverse == None: raise HTTPException(status_code=400, detail="No filter specified") if reason != None: reason = sub("(%|_)", "", reason) @@ -43,45 +68,46 @@ def blocked(domain: str = None, reason: str = None): if domain != None: wildchar = "*." + ".".join(domain.split(".")[-domain.count("."):]) punycode = domain.encode('idna').decode('utf-8') - c.execute("select blocker, blocked, block_level, reason from blocks where blocked = ? or blocked = ? or blocked = ? or blocked = ? or blocked = ? or blocked = ?", + c.execute("select blocker, blocked, block_level, reason, first_added, last_seen from blocks where blocked = ? or blocked = ? or blocked = ? or blocked = ? or blocked = ? or blocked = ? order by first_added asc", (domain, "*." + domain, wildchar, get_hash(domain), punycode, "*." + punycode)) + elif reverse != None: + c.execute("select blocker, blocked, block_level, reason, first_added, last_seen from blocks where blocker = ? order by first_added asc", (reverse,)) else: - c.execute("select blocker, blocked, reason, block_level from blocks where reason like ? and reason != ''", ("%"+reason+"%",)) + c.execute("select blocker, blocked, block_level, reason, first_added, last_seen from blocks where reason like ? and reason != '' order by first_added asc", ("%"+reason+"%",)) blocks = c.fetchall() - conn.close() + c.close() result = {} - reasons = {} - wildcards = [] - if domain != None: - for domain, blocked, block_level, reason in blocks: - if block_level in result: - result[block_level].append(domain) - else: - result[block_level] = [domain] - if blocked == "*." + ".".join(blocked.split(".")[-blocked.count("."):]): - wildcards.append(domain) - if reason != "": - if block_level in reasons: - reasons[block_level][domain] = reason - else: - reasons[block_level] = {domain: reason} - return {"blocks": result, "reasons": reasons, "wildcards": wildcards} - - for blocker, blocked, reason, block_level in blocks: + for blocker, blocked, block_level, reason, first_added, last_seen in blocks: + entry = {"blocker": blocker, "blocked": blocked, "reason": reason, "first_added": first_added, "last_seen": last_seen} if block_level in result: - result[block_level].append({"blocker": blocker, "blocked": blocked, "reason": reason}) + result[block_level].append(entry) else: - result[block_level] = [{"blocker": blocker, "blocked": blocked, "reason": reason}] - return {"blocks": result} + result[block_level] = [entry] + + return result + +@app.get(base_url+"/scoreboard") +def index(request: Request, blockers: int = None, blocked: int = None): + if blockers == None and blocked == None: + raise HTTPException(status_code=400, detail="No filter specified") + elif blockers != None: + scores = get(f"http://127.0.0.1:{port}{base_url}/top?blockers={blockers}") + elif blocked != None: + scores = get(f"http://127.0.0.1:{port}{base_url}/top?blocked={blocked}") + if scores != None: + if not scores.ok: + raise HTTPException(status_code=blocks.status_code, detail=blocks.text) + scores = scores.json() + return templates.TemplateResponse("index.html", {"request": request, "scoreboard": True, "blockers": blockers, "blocked": blocked, "scores": scores}) @app.get(base_url+"/") -def index(request: Request, domain: str = None, reason: str = None): - if domain == "" or reason == "": +def index(request: Request, domain: str = None, reason: str = None, reverse: str = None): + if domain == "" or reason == "" or reverse == "": return responses.RedirectResponse("/") info = None blocks = None - if domain == None and reason == None: + if domain == None and reason == None and reverse == None: info = get(f"http://127.0.0.1:{port}{base_url}/info") if not info.ok: raise HTTPException(status_code=info.status_code, detail=info.text) @@ -90,11 +116,18 @@ def index(request: Request, domain: str = None, reason: str = None): blocks = get(f"http://127.0.0.1:{port}{base_url}/api?domain={domain}") elif reason != None: blocks = get(f"http://127.0.0.1:{port}{base_url}/api?reason={reason}") + elif reverse != None: + blocks = get(f"http://127.0.0.1:{port}{base_url}/api?reverse={reverse}") if blocks != None: if not blocks.ok: raise HTTPException(status_code=blocks.status_code, detail=blocks.text) blocks = blocks.json() - return templates.TemplateResponse("index.html", {"request": request, "domain": domain, "blocks": blocks, "reason": reason, "info": info}) + for block_level in blocks: + for block in blocks[block_level]: + block["first_added"] = datetime.utcfromtimestamp(block["first_added"]).strftime('%Y-%m-%d %H:%M') + block["last_seen"] = datetime.utcfromtimestamp(block["last_seen"]).strftime('%Y-%m-%d %H:%M') + + return templates.TemplateResponse("index.html", {"request": request, "domain": domain, "blocks": blocks, "reason": reason, "reverse": reverse, "info": info}) if __name__ == "__main__": uvicorn.run("api:app", host="127.0.0.1", port=port, log_level="info") diff --git a/index.html b/index.html index 644bf1d..65afe7f 100644 --- a/index.html +++ b/index.html @@ -10,11 +10,33 @@ } .block_level { background-color: #1c1c3c; - width: 750px; + width: 80em; padding: 5px; margin: auto; margin-top: 10px; } + .scoreboard { + background-color: #1c1c3c; + width: 40em; + padding: 5px; + margin: auto; + margin-top: 10px; + } + table { + width: 100%; + background-color: #2d2d4d; + border-spacing: 0px; + } + table tr:nth-of-type(2n) { + background-color: #1c1c3c; + } + table td { + padding: 4px; + } + .block_level table td:nth-of-type(1), .block_level table td:nth-of-type(2), + .block_level table td:nth-of-type(4), .block_level table td:nth-of-type(5) { + white-space: nowrap; + } .block { background-color: #2d2d4d; padding: 5px; @@ -52,40 +74,60 @@
- {% if reason %} -Instance | +Defederations | + {% for entry in scores %} +
---|---|
+ + {{entry['domain']}} + | +{{entry['highscore']}} | +
Blocker | +{% if block_level == 'accept' %}Accepted{% else %}Blocked{% endif %} | +Reason | +First added | +Last seen | + {% for block in blocks[block_level] %} +
---|---|---|---|---|
+ + {{block['blocker']}} + | ++ + {{block['blocked']}} + | +{{block['reason']}} | +{{block['first_added']}} | +{{block['last_seen']}} | +
+ top 50 defederating / defederated instances +