minetest-api-py/getblocks.py

126 lines
3.0 KiB
Python

#!/usr/bin/env python3
import json, psycopg2, re, socket, time
CONFIG_DB_CONNECT = "host=127.0.0.1 port=5432 user=minetest password=PASSWORD dbname=minetest-world"
CONFIG_LISTEN = ("0.0.0.0", 8060)
RECBUF = 1024
p_clen = re.compile("\r?\ncontent-length: *(\d+)\r?\n?", re.IGNORECASE)
p_stmt = re.compile("^(x|y|z)(<|>|=|<=|>=)-?\d{1,5}$")
def send_response(client, code, resp):
try:
content_raw = json.dumps(resp).encode()
except TypeError:
content_raw = json.dumps({"error": "non_ascii_resp"}).encode()
mime = "text/json"
client.sendall(("HTTP/1.1 "+code+"\r\nContent-type: "+mime+"; charset=UTF-8\r\nAccess-Control-Allow-Origin: *\r\nContent-length: "+str(len(content_raw))+"\r\n\r\n").encode()+content_raw)
client.close()
if __name__ == "__main__":
conn = psycopg2.connect(CONFIG_DB_CONNECT)
server_addr = CONFIG_LISTEN
if ":" in server_addr[0]: # IPv6
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
else: # IPv4
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.settimeout(5)
sock.bind(server_addr)
sock.listen(1)
print("Server started at "+str(server_addr))
while True:
try:
client, addr = sock.accept()
except socket.timeout:
continue
# Get request
paquet = b""
header = b""
content = b""
content_len = 0
resp = {}
lf = 0
while True:
raw = client.recv(RECBUF)
if raw:
paquet += raw
if lf >= 0:
for c in raw:
if c == 10:# LF
lf += 1
elif c != 13:# CR
lf = 0
if lf > 1:
parts = paquet.split(b"\r\n\r\n")
header = parts[0]
content = parts[1]
try:
content_len = int(p_clen.search(header.decode()).group(1))
except (AttributeError, ValueError):
content_len = 0
break
if lf > 1:
break
else:
break
while len(content) < content_len:
raw = client.recv(RECBUF)
paquet += raw
content += raw
# Get URL
httpreq = paquet.split(b"\n")
try:
url = httpreq[0].split(b" ")[1].decode().split("/")
except IndexError:
send_response(client, "400 Bad Request", {"error": "bad_http"})
continue
while "" in url:
url.remove("")
urll = len(url)
if len(url) > 6:
send_response(client, "400 Bad Request", {"error": "too_many_statements"})
continue
if len(url) == 0:
send_response(client, "400 Bad Request", {"error": "no_statement"})
continue
stmts = []
bad = False
for stmt in url:
if not p_stmt.match(stmt):
bad = True
break
stmts.append("pos"+stmt)
if bad:
send_response(client, "400 Bad Request", {"error": "bad_statement"})
continue
req = " AND ".join(stmts)
cur = conn.cursor()
cur.execute("SELECT * FROM blocks WHERE "+req+" LIMIT 1000;")
resp["blocks"] = []
while True:
block = cur.fetchone()
if not block:
break
resp["blocks"].append([block[0], block[1], block[2], block[3].hex()])
print(req)
# Send response
send_response(client, "200 OK", resp)
time.sleep(.2)