Major frontend & API rehaul
This commit is contained in:
parent
614aef2762
commit
6dd4da5cfb
91
api.py
91
api.py
@ -6,6 +6,7 @@ from fastapi.templating import Jinja2Templates
|
|||||||
from requests import get
|
from requests import get
|
||||||
from json import loads
|
from json import loads
|
||||||
from re import sub
|
from re import sub
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
with open("config.json") as f:
|
with open("config.json") as f:
|
||||||
config = loads(f.read())
|
config = loads(f.read())
|
||||||
@ -30,9 +31,33 @@ def info():
|
|||||||
"blocks_recorded": blocks
|
"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")
|
@app.get(base_url+"/api")
|
||||||
def blocked(domain: str = None, reason: str = None):
|
def blocked(domain: str = None, reason: str = None, reverse: str = None):
|
||||||
if domain == None and reason == None:
|
if domain == None and reason == None and reverse == None:
|
||||||
raise HTTPException(status_code=400, detail="No filter specified")
|
raise HTTPException(status_code=400, detail="No filter specified")
|
||||||
if reason != None:
|
if reason != None:
|
||||||
reason = sub("(%|_)", "", reason)
|
reason = sub("(%|_)", "", reason)
|
||||||
@ -43,45 +68,46 @@ def blocked(domain: str = None, reason: str = None):
|
|||||||
if domain != None:
|
if domain != None:
|
||||||
wildchar = "*." + ".".join(domain.split(".")[-domain.count("."):])
|
wildchar = "*." + ".".join(domain.split(".")[-domain.count("."):])
|
||||||
punycode = domain.encode('idna').decode('utf-8')
|
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))
|
(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:
|
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()
|
blocks = c.fetchall()
|
||||||
conn.close()
|
c.close()
|
||||||
|
|
||||||
result = {}
|
result = {}
|
||||||
reasons = {}
|
for blocker, blocked, block_level, reason, first_added, last_seen in blocks:
|
||||||
wildcards = []
|
entry = {"blocker": blocker, "blocked": blocked, "reason": reason, "first_added": first_added, "last_seen": last_seen}
|
||||||
if domain != None:
|
|
||||||
for domain, blocked, block_level, reason in blocks:
|
|
||||||
if block_level in result:
|
if block_level in result:
|
||||||
result[block_level].append(domain)
|
result[block_level].append(entry)
|
||||||
else:
|
else:
|
||||||
result[block_level] = [domain]
|
result[block_level] = [entry]
|
||||||
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:
|
return result
|
||||||
if block_level in result:
|
|
||||||
result[block_level].append({"blocker": blocker, "blocked": blocked, "reason": reason})
|
@app.get(base_url+"/scoreboard")
|
||||||
else:
|
def index(request: Request, blockers: int = None, blocked: int = None):
|
||||||
result[block_level] = [{"blocker": blocker, "blocked": blocked, "reason": reason}]
|
if blockers == None and blocked == None:
|
||||||
return {"blocks": result}
|
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+"/")
|
@app.get(base_url+"/")
|
||||||
def index(request: Request, domain: str = None, reason: str = None):
|
def index(request: Request, domain: str = None, reason: str = None, reverse: str = None):
|
||||||
if domain == "" or reason == "":
|
if domain == "" or reason == "" or reverse == "":
|
||||||
return responses.RedirectResponse("/")
|
return responses.RedirectResponse("/")
|
||||||
info = None
|
info = None
|
||||||
blocks = 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")
|
info = get(f"http://127.0.0.1:{port}{base_url}/info")
|
||||||
if not info.ok:
|
if not info.ok:
|
||||||
raise HTTPException(status_code=info.status_code, detail=info.text)
|
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}")
|
blocks = get(f"http://127.0.0.1:{port}{base_url}/api?domain={domain}")
|
||||||
elif reason != None:
|
elif reason != None:
|
||||||
blocks = get(f"http://127.0.0.1:{port}{base_url}/api?reason={reason}")
|
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 blocks != None:
|
||||||
if not blocks.ok:
|
if not blocks.ok:
|
||||||
raise HTTPException(status_code=blocks.status_code, detail=blocks.text)
|
raise HTTPException(status_code=blocks.status_code, detail=blocks.text)
|
||||||
blocks = blocks.json()
|
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__":
|
if __name__ == "__main__":
|
||||||
uvicorn.run("api:app", host="127.0.0.1", port=port, log_level="info")
|
uvicorn.run("api:app", host="127.0.0.1", port=port, log_level="info")
|
||||||
|
113
index.html
113
index.html
@ -10,11 +10,33 @@
|
|||||||
}
|
}
|
||||||
.block_level {
|
.block_level {
|
||||||
background-color: #1c1c3c;
|
background-color: #1c1c3c;
|
||||||
width: 750px;
|
width: 80em;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
margin-top: 10px;
|
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 {
|
.block {
|
||||||
background-color: #2d2d4d;
|
background-color: #2d2d4d;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
@ -52,40 +74,60 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
{% if scoreboard %}
|
||||||
|
{% if blockers %}
|
||||||
|
<h1>Top {{blockers}} defederating instances</h1>
|
||||||
|
{% elif blocked %}
|
||||||
|
<h1>Top {{blocked}} defederated instances</h1>
|
||||||
|
{% endif %}
|
||||||
|
<div class="scoreboard">
|
||||||
|
<table>
|
||||||
|
<th>Instance</th>
|
||||||
|
<th>Defederations</th>
|
||||||
|
{% for entry in scores %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<img src="https://proxy.duckduckgo.com/ip3/{{entry['domain']}}.ico" width=16/>
|
||||||
|
<b><a href="https://{{entry['domain']}}" rel="nofollow noopener noreferrer">{{entry['domain']}}</a></b>
|
||||||
|
</td>
|
||||||
|
<td>{{entry['highscore']}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% elif reason or blocks or reverse %}
|
||||||
{% if reason %}
|
{% if reason %}
|
||||||
<h1>Instances that use "{{reason}}" in their Reason</h1>
|
<h1>Instances that use "{{reason}}" in their reason</h1>
|
||||||
{% for block_level in blocks.blocks %}
|
{% elif reverse %}
|
||||||
<div class="block_level">
|
<h1>Instances that are blocked by {{reverse}}</h1>
|
||||||
<h2>{{block_level}} ({{blocks.blocks[block_level]|length}})</h2>
|
|
||||||
{% for block in blocks.blocks[block_level] %}
|
|
||||||
<div class="block">
|
|
||||||
<img src="https://proxy.duckduckgo.com/ip3/{{block.blocker}}.ico" width=16/>
|
|
||||||
<b><a href="https://{{block.blocker}}" rel="nofollow noopener noreferrer">{{block.blocker}}</a></b> ->
|
|
||||||
<img src="https://proxy.duckduckgo.com/ip3/{{block.blocked}}.ico" width=16/>
|
|
||||||
<b><a href="https://{{block.blocked}}" rel="nofollow noopener noreferrer">{{block.blocked}}</a></b><br/>
|
|
||||||
{{block.reason}}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% elif blocks %}
|
{% elif blocks %}
|
||||||
<h1>Instances that block {{domain}}</h1>
|
<h1>Instances that block {{domain}}</h1>
|
||||||
{% for block_level in blocks.blocks %}
|
{% endif %}
|
||||||
|
{% for block_level in blocks %}
|
||||||
<div class="block_level" id="{{block_level}}">
|
<div class="block_level" id="{{block_level}}">
|
||||||
<h2>{{block_level}} ({{blocks.blocks[block_level]|length}})</h2>
|
<h2>{{block_level}} ({{blocks[block_level]|length}})</h2>
|
||||||
{% for block in blocks.blocks[block_level] %}
|
<table>
|
||||||
<div class="block">
|
<th>Blocker</th>
|
||||||
<img src="https://proxy.duckduckgo.com/ip3/{{block}}.ico" width=16/>
|
<th>{% if block_level == 'accept' %}Accepted{% else %}Blocked{% endif %}</th>
|
||||||
<b><a href="https://{{block}}" rel="nofollow noopener noreferrer">{{block}}</a></b>
|
<th>Reason</th>
|
||||||
{% if block in blocks.wildcards %}
|
<th>First added</th>
|
||||||
(<span title="wildcard block">∗</span>)
|
<th>Last seen</th>
|
||||||
{% endif %}
|
{% for block in blocks[block_level] %}
|
||||||
<br/>
|
<tr>
|
||||||
{% if block_level in blocks.reasons %}
|
<td>
|
||||||
{{blocks.reasons[block_level][block]}}
|
<img src="https://proxy.duckduckgo.com/ip3/{{block['blocker']}}.ico" width=16/>
|
||||||
{% endif %}
|
<b><a href="https://{{block['blocker']}}" rel="nofollow noopener noreferrer">{{block['blocker']}}</a></b>
|
||||||
</div>
|
</td>
|
||||||
|
<td>
|
||||||
|
<img src="https://proxy.duckduckgo.com/ip3/{{domain or block['blocked']}}.ico" width=16/>
|
||||||
|
<b><a href="https://{{domain or block['blocked']}}" rel="nofollow noopener noreferrer">{{block['blocked']}}</a></b>
|
||||||
|
</td>
|
||||||
|
<td>{{block['reason']}}</td>
|
||||||
|
<td>{{block['first_added']}}</td>
|
||||||
|
<td>{{block['last_seen']}}</td>
|
||||||
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
@ -99,11 +141,20 @@
|
|||||||
<input type="text" name="reason" placeholder="free speech" />
|
<input type="text" name="reason" placeholder="free speech" />
|
||||||
<input type="submit" value="Submit" />
|
<input type="submit" value="Submit" />
|
||||||
</form>
|
</form>
|
||||||
|
<h1>Reverse search</h1>
|
||||||
|
<form>
|
||||||
|
<input type="text" name="reverse" placeholder="example.com" />
|
||||||
|
<input type="submit" value="Submit" />
|
||||||
|
</form>
|
||||||
|
<p>
|
||||||
|
<a href="./scoreboard?blockers=50">top 50 defederating</a> / <a href="./scoreboard?blocked=50">defederated instances</a>
|
||||||
|
</p>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
known instances: {{info.known_instances}}<br/>
|
known instances: {{info.known_instances}}<br/>
|
||||||
indexed instances: {{info.indexed_instances}}<br/>
|
indexed instances: {{info.indexed_instances}}<br/>
|
||||||
blocks recorded: {{info.blocks_recorded}}<br/>
|
blocks recorded: {{info.blocks_recorded}}<br/>
|
||||||
source code: <a href="https://git.kiwifarms.net/mint/fedi-block-api">git.kiwifarms.net/mint/fedi-block-api</a> (<a href="https://gitgud.io/mintplg/fedi-block-api">mirror</a>)
|
source code: <a href="https://git.kiwifarms.net/mint/fedi-block-api">git.kiwifarms.net/mint/fedi-block-api</a> (<a href="https://gitgud.io/mintplg/fedi-block-api">mirror</a>)<br/>
|
||||||
|
fuck jannies
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</body>
|
</body>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user