fedi-block-api/api.py

102 lines
4.2 KiB
Python
Raw Normal View History

2022-04-22 18:56:58 +00:00
import uvicorn
2022-04-22 18:42:39 +00:00
from fastapi import FastAPI, Request, HTTPException, responses
2022-03-31 21:09:13 +00:00
import sqlite3
2022-04-22 12:58:23 +00:00
from hashlib import sha256
2022-04-22 17:49:23 +00:00
from fastapi.templating import Jinja2Templates
from requests import get
2022-04-22 18:56:58 +00:00
from json import loads
2022-11-29 19:36:46 +00:00
from re import sub
2022-03-31 21:09:13 +00:00
2022-04-22 18:56:58 +00:00
with open("config.json") as f:
config = loads(f.read())
base_url = config["base_url"]
port = config["port"]
2022-03-31 21:09:13 +00:00
app = FastAPI(docs_url=base_url+"/docs", redoc_url=base_url+"/redoc")
2022-04-22 17:49:23 +00:00
templates = Jinja2Templates(directory=".")
2022-03-31 21:09:13 +00:00
2022-04-22 12:58:23 +00:00
def get_hash(domain: str) -> str:
return sha256(domain.encode("utf-8")).hexdigest()
2022-03-31 21:09:13 +00:00
@app.get(base_url+"/info")
def info():
conn = sqlite3.connect("blocks.db")
c = conn.cursor()
c.execute("select (select count(domain) from instances), (select count(domain) from instances where software in ('pleroma', 'mastodon', 'misskey', 'gotosocial', 'friendica')), (select count(blocker) from blocks)")
2022-03-31 21:09:13 +00:00
known, indexed, blocks = c.fetchone()
c.close()
return {
"known_instances": known,
"indexed_instances": indexed,
"blocks_recorded": blocks,
2022-07-22 20:56:46 +00:00
"source_code": "https://git.kiwifarms.net/mint/fedi-block-api",
2022-03-31 21:09:13 +00:00
}
2022-04-22 17:49:23 +00:00
@app.get(base_url+"/api")
2022-04-23 13:06:31 +00:00
def blocked(domain: str = None, reason: str = None):
if domain == None and reason == None:
raise HTTPException(status_code=400, detail="No filter specified")
2022-11-29 19:36:46 +00:00
if reason != None:
reason = sub("(%|_)", "", reason)
if len(reason) < 3:
raise HTTPException(status_code=400, detail="Keyword is shorter than three characters")
2022-11-27 20:04:45 +00:00
conn = sqlite3.connect("blocks.db")
2022-03-31 21:09:13 +00:00
c = conn.cursor()
2022-04-23 13:06:31 +00:00
if domain != None:
wildchar = "*." + ".".join(domain.split(".")[-domain.count("."):])
2022-08-08 11:11:01 +00:00
punycode = domain.encode('idna').decode('utf-8')
2022-08-08 11:29:44 +00:00
c.execute("select blocker, blocked, block_level, reason from blocks where blocked = ? or blocked = ? or blocked = ? or blocked = ? or blocked = ? or blocked = ?",
2022-08-08 11:11:01 +00:00
(domain, "*." + domain, wildchar, get_hash(domain), punycode, "*." + punycode))
2022-04-23 13:06:31 +00:00
else:
2022-11-29 19:36:46 +00:00
c.execute("select blocker, blocked, reason, block_level from blocks where reason like ? and reason != ''", ("%"+reason+"%",))
2022-03-31 21:09:13 +00:00
blocks = c.fetchall()
conn.close()
result = {}
reasons = {}
2022-08-08 11:31:45 +00:00
wildcards = []
2022-04-23 13:06:31 +00:00
if domain != None:
2022-08-08 11:29:44 +00:00
for domain, blocked, block_level, reason in blocks:
2022-04-23 13:06:31 +00:00
if block_level in result:
result[block_level].append(domain)
else:
result[block_level] = [domain]
2022-08-08 11:29:44 +00:00
if blocked == "*." + ".".join(blocked.split(".")[-blocked.count("."):]):
wildcards.append(domain)
2022-04-23 13:06:31 +00:00
if reason != "":
if block_level in reasons:
reasons[block_level][domain] = reason
else:
reasons[block_level] = {domain: reason}
2022-08-08 11:29:44 +00:00
return {"blocks": result, "reasons": reasons, "wildcards": wildcards}
2022-04-14 12:04:53 +00:00
2022-04-23 13:06:31 +00:00
for blocker, blocked, reason, block_level in blocks:
if block_level in result:
2022-04-23 13:06:31 +00:00
result[block_level].append({"blocker": blocker, "blocked": blocked, "reason": reason})
else:
2022-04-23 13:06:31 +00:00
result[block_level] = [{"blocker": blocker, "blocked": blocked, "reason": reason}]
return {"blocks": result}
2022-03-31 21:09:13 +00:00
2022-04-22 17:49:23 +00:00
@app.get(base_url+"/")
2022-08-08 11:38:04 +00:00
def index(request: Request, domain: str = None, reason: str = None):
2022-04-23 13:06:31 +00:00
if domain == "" or reason == "":
2022-04-22 18:42:39 +00:00
return responses.RedirectResponse("/")
2022-04-22 17:49:23 +00:00
info = None
2022-04-23 13:06:31 +00:00
blocks = None
if domain == None and reason == None:
2022-04-22 18:56:58 +00:00
info = get(f"http://127.0.0.1:{port}{base_url}/info")
2022-04-22 17:49:23 +00:00
if not info.ok:
raise HTTPException(status_code=info.status_code, detail=info.text)
info = info.json()
2022-04-23 13:06:31 +00:00
elif domain != 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}")
if blocks != None:
if not blocks.ok:
raise HTTPException(status_code=blocks.status_code, detail=blocks.text)
blocks = blocks.json()
2022-08-08 11:38:04 +00:00
return templates.TemplateResponse("index.html", {"request": request, "domain": domain, "blocks": blocks, "reason": reason, "info": info})
2022-04-22 18:56:58 +00:00
if __name__ == "__main__":
uvicorn.run("api:app", host="127.0.0.1", port=port, log_level="info")