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-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 ( )
2022-11-07 21:26:47 +00:00
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-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-27 20:02:12 +00:00
if len ( reason ) < 3 :
raise HTTPException ( status_code = 400 , detail = " Keyword is shorter than three characters " )
else :
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 ( )
2022-04-14 18:26:19 +00:00
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 :
2022-04-14 18:26:19 +00:00
if block_level in result :
2022-04-23 13:06:31 +00:00
result [ block_level ] . append ( { " blocker " : blocker , " blocked " : blocked , " reason " : reason } )
2022-04-14 18:26:19 +00:00
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 " )