Initial commit: Astro scaffold, review template, voorstelformulier, screenshot/AI-automatisering

This commit is contained in:
2026-07-24 08:54:47 +02:00
commit 0913c99b9b
23 changed files with 6027 additions and 0 deletions

87
server/cgi-bin/submit-tool.py Executable file
View File

@@ -0,0 +1,87 @@
#!/usr/bin/env python3
"""CGI-handler voor het tool-voorstelformulier op aitestbank.nl.
Ontvangt een gewone (niet-JS) form-POST, mailt de inzending via de lokale
Postfix (localhost:25) en redirect naar /bedankt. Stdlib-only, bewust geen
`cgi`-module (die is deprecated/verwijderd vanaf Python 3.13).
"""
import html
import os
import smtplib
import sys
from email.message import EmailMessage
from urllib.parse import parse_qs
# TODO: zet hier het gewenste ontvangstadres
TO_ADDR = "mjblom@gmail.com"
FROM_ADDR = "aitestbank@b10m.net"
MAX_BODY_BYTES = 20_000
def redirect(location: str) -> None:
sys.stdout.write(f"Status: 303 See Other\r\nLocation: {location}\r\n\r\n")
def bad_request(message: str) -> None:
sys.stdout.write("Status: 400 Bad Request\r\nContent-Type: text/html; charset=utf-8\r\n\r\n")
sys.stdout.write(
f'<!doctype html><html lang="nl"><body>'
f"<p>{html.escape(message)}</p>"
f'<p><a href="/voorstellen">Terug naar het formulier</a></p>'
f"</body></html>"
)
def main() -> None:
length = int(os.environ.get("CONTENT_LENGTH", 0) or 0)
if length <= 0 or length > MAX_BODY_BYTES:
bad_request("Ongeldige of te grote inzending.")
return
raw = sys.stdin.buffer.read(length).decode("utf-8", errors="replace")
fields = parse_qs(raw)
def field(name: str) -> str:
return fields.get(name, [""])[0].strip()
# Honeypot: onzichtbaar veld voor mensen, bots vullen het vaak wel in.
if field("website"):
redirect("/bedankt")
return
tool_naam = field("tool_naam")
tool_url = field("tool_url")
naam = field("naam")
email = field("email")
toelichting = field("toelichting")
if not tool_naam or not tool_url:
bad_request("Tool-naam en tool-URL zijn verplicht.")
return
body = (
"Nieuwe tool-suggestie via aitestbank.nl/voorstellen\n\n"
f"Tool: {tool_naam}\n"
f"URL: {tool_url}\n"
f"Naam indiener: {naam or '(niet opgegeven)'}\n"
f"E-mail indiener: {email or '(niet opgegeven)'}\n\n"
"Toelichting:\n"
f"{toelichting or '(geen)'}\n"
)
msg = EmailMessage()
msg["Subject"] = f"Tool-suggestie: {tool_naam}"
msg["From"] = FROM_ADDR
msg["To"] = TO_ADDR
if email:
msg["Reply-To"] = email
msg.set_content(body)
with smtplib.SMTP("localhost", 25) as smtp:
smtp.send_message(msg)
redirect("/bedankt")
if __name__ == "__main__":
main()