Gem2Browser/server.py

123 lines
5.1 KiB
Python
Raw Normal View History

2025-01-12 21:36:58 -08:00
#!/usr/bin/python3
2025-01-12 22:31:01 -08:00
import asyncio, traceback, socket, ssl
2025-01-12 22:37:07 -08:00
from urllib.parse import urlparse
2025-01-13 15:53:40 -08:00
from flask import Flask, request, redirect, send_file
2025-01-12 21:36:58 -08:00
from hypercorn.config import Config
from hypercorn.asyncio import serve
app = Flask(__name__)
@app.route("/")
def root():
2025-01-12 22:00:24 -08:00
return """
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
2025-01-13 15:55:48 -08:00
<link rel="stylesheet" href="/style.css">
2025-01-12 22:00:24 -08:00
<title>Gem2Browser</title>
</head>
<body>
<center>
<h1>Gem2Browser</h1>
<form action="/gem">
2025-01-13 15:55:48 -08:00
<p>gemini://<input class="input" value="geminiprotocol.net" type="text" name="gemini"></p><br>
<input type="submit" class="go" value="Go!">
2025-01-12 22:00:24 -08:00
</form>
</center>
</body>
</html>
"""
2025-01-13 15:53:40 -08:00
@app.route("/external.png")
def external():
return send_file("external.png")
@app.route("/cross-server.png")
2025-01-13 15:55:48 -08:00
def crosserver():
return send_file("cross-server.png")
@app.route("/style.css")
2025-01-13 16:00:57 -08:00
def style():
2025-01-13 15:53:40 -08:00
return send_file("cross-server.png")
2025-01-12 21:51:59 -08:00
@app.route("/gem")
def relay():
url = request.args.get('gemini')
if url == None:
return redirect("/")
2025-01-12 22:00:24 -08:00
code = "<h1>Something went wrong...</h1>\n"
2025-01-12 21:36:58 -08:00
title = "Something went wrong..."
try:
2025-01-12 22:31:01 -08:00
gsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
2025-01-12 22:37:07 -08:00
fulladdr = "gemini://" + url
2025-01-12 22:39:23 -08:00
gemsocket = ssl._create_unverified_context().wrap_socket(gsocket, server_hostname=urlparse(fulladdr).hostname)
2025-01-12 22:37:07 -08:00
gemsocket.connect((urlparse(fulladdr).hostname, 1965))
2025-01-12 22:31:01 -08:00
gemsocket.send(bytes("gemini://" + url + "\r\n", "UTF-8"))
received = ""
while True:
gemresponse = gemsocket.recv(2048)
2025-01-13 15:18:24 -08:00
if gemresponse.decode() != "":
2025-01-12 22:31:01 -08:00
received += gemresponse.decode()
else:
break
received = received.replace("\r", "")
firstline = True
redirected = False
gemtext = True
code = ""
for i in received.split("\n"):
if firstline:
if i.split(" ")[0][0] == "3":
2025-01-12 22:43:10 -08:00
return redirect("/gem?gemini=" + i.split(" ")[1][9:])
2025-01-12 22:31:01 -08:00
elif i.split(" ")[0][0] != "2":
return f'<!DOCTYPE html>\n<html><head><meta charset="UTF-8"><link rel="stylesheet" href="https://swee.codes/style.css"><title>Something went wrong...</title></head><body><h1>Something went wrong...</h1><p>The specified Gemini server returned a status of: {i}</p></body></html>'
else:
firstline = False
if i.split(" ")[1] != "text/gemini":
return f'<!DOCTYPE html>\n<html><head><meta charset="UTF-8"><link rel="stylesheet" href="https://swee.codes/style.css"><title>Something went wrong...</title></head><body><h1>Something went wrong...</h1><p>This path returned a file that isn\'t Gemtext, which Gem2Browser doesn\'t support downloading files.</p></body></html>'
else:
2025-01-13 15:28:42 -08:00
if i[0:2] == "# ":
2025-01-12 22:31:01 -08:00
if title == "Something went wrong...":
title = i[2:]
temp = i[2:]
code += f"<h1>{temp}</h1>\n"
2025-01-13 15:28:42 -08:00
elif i[0:3] == "## ":
2025-01-12 22:31:01 -08:00
temp = i[3:]
code += f"<h2>{temp}</h2>\n"
2025-01-13 15:28:42 -08:00
elif i[0:4] == "### ":
2025-01-12 22:31:01 -08:00
temp = i[4:]
code += f"<h3>{temp}</h3>\n"
2025-01-13 15:28:42 -08:00
elif i[0:2] == "* ":
2025-01-12 22:31:01 -08:00
temp = i[2:]
2025-01-13 15:53:40 -08:00
code += f"<ul><li>{temp}</li></ul>\n"
elif i[0:2] == "=>":
temp = i[2:].strip()
goto = temp.split(" ")[0]
prse = urlparse(goto)
extra = ""
2025-01-13 16:00:33 -08:00
print(goto)
2025-01-13 15:53:40 -08:00
if prse.netloc == "" and prse.scheme == "":
isdir = url[len(url) - 1] == "/"
if isdir:
2025-01-13 16:00:33 -08:00
print(url + goto)
2025-01-13 15:53:40 -08:00
tempurl = url + goto
else:
tempurl = "/".join(url.split("/")[:-1]) + "/" + goto
goto = f"/gem?gemini={tempurl}"
2025-01-13 16:00:33 -08:00
print(goto)
2025-01-13 15:53:40 -08:00
elif prse.scheme != "gemini":
2025-01-13 15:55:48 -08:00
extra = "<img height=\"6\" src=\"/external.png\">"
2025-01-13 15:53:40 -08:00
elif prse.hostname != urlparse(fulladdr).hostname:
2025-01-13 15:55:48 -08:00
extra = "<img height=\"6\" src=\"/cross-server.png\">"
2025-01-13 15:53:40 -08:00
if temp.split(" ") == 1:
comment = goto
else:
comment = " ".join(temp.split(" ")[1:])
2025-01-13 16:00:33 -08:00
code += f"<p><a href=\"{goto}\">{comment} {extra}</a></p>\n"
2025-01-12 22:31:01 -08:00
else:
2025-01-13 15:27:48 -08:00
code += f"<p>{i}</p>\n"
2025-01-12 22:31:01 -08:00
if title == "Something went wrong...":
title = "gemini://" + url
2025-01-12 21:36:58 -08:00
except:
2025-01-12 22:00:24 -08:00
code += traceback.format_exc()
2025-01-13 15:55:48 -08:00
return f'<!DOCTYPE html>\n<html><head><meta charset="UTF-8"><link rel="stylesheet" href="/style.css"><title>{title}</title></head><body>{code}</body></html>'
2025-01-12 21:36:58 -08:00
# Run the Hypercorn ASGI server
2025-01-12 21:49:36 -08:00
conf = Config()
conf.bind = "0.0.0.0:2009"
asyncio.run(serve(app, conf))