386 lines
15 KiB
Python
Executable File
386 lines
15 KiB
Python
Executable File
import os
|
|
import re
|
|
import smtplib
|
|
from email.mime.text import MIMEText
|
|
from xml.etree.ElementTree import Element, SubElement, tostring
|
|
|
|
from bibapi import catalogue
|
|
from fastapi import FastAPI, Form, HTTPException, Request, status
|
|
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse
|
|
from fastapi.staticfiles import StaticFiles
|
|
from fastapi.templating import Jinja2Templates
|
|
|
|
app = FastAPI()
|
|
templates = Jinja2Templates(directory="app/templates")
|
|
|
|
# Serve static files (CSS, images)
|
|
app.mount("/static", StaticFiles(directory="app/static"), name="static")
|
|
|
|
# Initialize catalogue for signature validation
|
|
cat = catalogue.Catalogue()
|
|
|
|
# add somewhere near the top-level constants
|
|
EMAIL_REGEX = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")
|
|
|
|
# SMTP / email configuration via environment
|
|
MAIL_ENABLED = os.getenv("MAIL_ENABLED", "false").lower() == "true"
|
|
SMTP_HOST = os.getenv("SMTP_HOST", "smtp")
|
|
SMTP_PORT = int(os.getenv("SMTP_PORT", "25"))
|
|
MAIL_FROM = os.getenv("MAIL_FROM", "noreply@example.com")
|
|
MAIL_TO = os.getenv("MAIL_TO", "destination@example.com")
|
|
|
|
|
|
@app.get("/", response_class=HTMLResponse)
|
|
async def landing_page(request: Request):
|
|
"""Landing page with service selection"""
|
|
return templates.TemplateResponse("index.html", {"request": request})
|
|
|
|
|
|
@app.get("/semesterapparat", response_class=HTMLResponse)
|
|
async def semesterapparat_form(request: Request):
|
|
"""Semesterapparat form page"""
|
|
return templates.TemplateResponse("semesterapparat_form.html", {"request": request})
|
|
|
|
|
|
@app.get("/elsa", response_class=HTMLResponse)
|
|
async def elsa_form(request: Request):
|
|
"""ELSA form page"""
|
|
return templates.TemplateResponse("elsa_mono_form.html", {"request": request})
|
|
|
|
|
|
@app.get("/api/validate-signature")
|
|
async def validate_signature(signature: str):
|
|
"""Validate a book signature and return total pages"""
|
|
try:
|
|
book_result = cat.get_book_with_data(signature)
|
|
if book_result and hasattr(book_result, "pages") and book_result.pages:
|
|
# Try to extract numeric page count
|
|
pages_str = str(book_result.pages)
|
|
# Extract first number from pages string (e.g., "245 S." -> 245)
|
|
match = re.search(r"(\d+)", pages_str)
|
|
if match:
|
|
total_pages = int(match.group(1))
|
|
return JSONResponse(
|
|
{"valid": True, "total_pages": total_pages, "signature": signature}
|
|
)
|
|
|
|
return JSONResponse(
|
|
{
|
|
"valid": False,
|
|
"error": "Signatur nicht gefunden oder keine Seitenzahl verfügbar",
|
|
"signature": signature,
|
|
}
|
|
)
|
|
except Exception as e:
|
|
return JSONResponse(
|
|
{
|
|
"valid": False,
|
|
"error": f"Fehler bei der Validierung: {str(e)}",
|
|
"signature": signature,
|
|
}
|
|
)
|
|
|
|
|
|
@app.post("/submit")
|
|
async def handle_form(
|
|
request: Request,
|
|
name: str = Form(...),
|
|
lastname: str = Form(...),
|
|
title: str = Form(...),
|
|
telno: str = Form(...),
|
|
mail: str = Form(...),
|
|
apparatsname: str = Form(...),
|
|
subject: str = Form(...),
|
|
semester_type: str = Form(...), # "summer" or "winter"
|
|
semester_year: str = Form(...),
|
|
authorname: list[str] = Form(...),
|
|
year: list[str] = Form(...),
|
|
booktitle: list[str] = Form(...),
|
|
signature: list[str] = Form(...),
|
|
message: str = Form(default=""),
|
|
):
|
|
# Basic email validation (server-side)
|
|
if not EMAIL_REGEX.match(mail):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Invalid email address format.",
|
|
)
|
|
|
|
# Build XML
|
|
root = Element("form_submission")
|
|
|
|
static_data = SubElement(root, "static")
|
|
SubElement(static_data, "name").text = name
|
|
SubElement(static_data, "lastname").text = lastname
|
|
SubElement(static_data, "title").text = title
|
|
SubElement(static_data, "telno").text = telno
|
|
SubElement(static_data, "mail").text = mail
|
|
SubElement(static_data, "apparatsname").text = apparatsname
|
|
SubElement(static_data, "subject").text = subject
|
|
SubElement(static_data, "semester").text = f"{semester_type} {semester_year}"
|
|
if message:
|
|
SubElement(static_data, "message").text = message
|
|
books = SubElement(root, "books")
|
|
for i in range(len(authorname)):
|
|
book = SubElement(books, "book")
|
|
SubElement(book, "authorname").text = authorname[i]
|
|
SubElement(book, "year").text = year[i]
|
|
SubElement(book, "title").text = booktitle[i]
|
|
SubElement(book, "signature").text = signature[i]
|
|
|
|
xml_data = tostring(root, encoding="unicode")
|
|
|
|
# Send mail
|
|
msg = MIMEText(xml_data, "xml")
|
|
msg["Subject"] = "New Form Submission"
|
|
msg["From"] = MAIL_FROM
|
|
msg["To"] = MAIL_TO
|
|
|
|
if MAIL_ENABLED:
|
|
with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server:
|
|
server.send_message(msg)
|
|
else:
|
|
print("=" * 80)
|
|
print("MAIL SENDING DISABLED - Would have sent:")
|
|
print(f"From: {MAIL_FROM}")
|
|
print(f"To: {MAIL_TO}")
|
|
print(f"Subject: {msg['Subject']}")
|
|
print("-" * 80)
|
|
print(xml_data)
|
|
print("=" * 80)
|
|
|
|
return RedirectResponse("/?success=true", status_code=303)
|
|
|
|
|
|
@app.post("/elsa/submit")
|
|
async def handle_elsa_form(request: Request):
|
|
"""Handle ELSA form submission with multiple media types"""
|
|
form_data = await request.form()
|
|
|
|
# Extract general information
|
|
name = str(form_data.get("name", ""))
|
|
lastname = str(form_data.get("lastname", ""))
|
|
title_field = str(form_data.get("title", ""))
|
|
mail = str(form_data.get("mail", ""))
|
|
subject = str(form_data.get("subject", ""))
|
|
classname = str(form_data.get("classname", ""))
|
|
usage_date_from = str(form_data.get("usage_date_from", ""))
|
|
usage_date_to = str(form_data.get("usage_date_to", ""))
|
|
availability_date = str(form_data.get("availability_date", ""))
|
|
message = str(form_data.get("message", ""))
|
|
|
|
# Basic email validation
|
|
if not EMAIL_REGEX.match(mail):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Invalid email address format.",
|
|
)
|
|
|
|
# Build XML structure
|
|
root = Element("elsa_submission")
|
|
|
|
# General information
|
|
general_info = SubElement(root, "general_info")
|
|
SubElement(general_info, "name").text = name
|
|
SubElement(general_info, "lastname").text = lastname
|
|
SubElement(general_info, "title").text = title_field
|
|
SubElement(general_info, "mail").text = mail
|
|
SubElement(general_info, "subject").text = subject
|
|
SubElement(general_info, "classname").text = classname
|
|
SubElement(general_info, "usage_date_from").text = usage_date_from
|
|
SubElement(general_info, "usage_date_to").text = usage_date_to
|
|
SubElement(general_info, "availability_date").text = availability_date
|
|
if message:
|
|
SubElement(general_info, "message").text = message
|
|
|
|
# Process media sections
|
|
media_root = SubElement(root, "media")
|
|
|
|
# Process Monografie entries
|
|
if "monografie_author[]" in form_data:
|
|
monografie_authors = [str(v) for v in form_data.getlist("monografie_author[]")]
|
|
monografie_years = [str(v) for v in form_data.getlist("monografie_year[]")]
|
|
monografie_editions = [
|
|
str(v) for v in form_data.getlist("monografie_edition[]")
|
|
]
|
|
monografie_titles = [str(v) for v in form_data.getlist("monografie_title[]")]
|
|
monografie_signatures = [
|
|
str(v) for v in form_data.getlist("monografie_signature[]")
|
|
]
|
|
monografie_pages_from = [
|
|
str(v) for v in form_data.getlist("monografie_pages_from[]")
|
|
]
|
|
monografie_pages_to = [
|
|
str(v) for v in form_data.getlist("monografie_pages_to[]")
|
|
]
|
|
|
|
# Get section IDs from the form (assuming they're in data-section attributes)
|
|
# Since we can't directly access data-section from form_data, we'll process sequentially
|
|
monografie_section = SubElement(media_root, "monografien")
|
|
for i in range(len(monografie_authors)):
|
|
entry = SubElement(monografie_section, "entry")
|
|
SubElement(entry, "author").text = (
|
|
monografie_authors[i] if i < len(monografie_authors) else ""
|
|
)
|
|
SubElement(entry, "year").text = (
|
|
monografie_years[i] if i < len(monografie_years) else ""
|
|
)
|
|
SubElement(entry, "edition").text = (
|
|
monografie_editions[i] if i < len(monografie_editions) else ""
|
|
)
|
|
SubElement(entry, "title").text = (
|
|
monografie_titles[i] if i < len(monografie_titles) else ""
|
|
)
|
|
SubElement(entry, "signature").text = (
|
|
monografie_signatures[i] if i < len(monografie_signatures) else ""
|
|
)
|
|
SubElement(entry, "pages_from").text = (
|
|
monografie_pages_from[i] if i < len(monografie_pages_from) else ""
|
|
)
|
|
SubElement(entry, "pages_to").text = (
|
|
monografie_pages_to[i] if i < len(monografie_pages_to) else ""
|
|
)
|
|
|
|
# Process Zeitschriftenartikel entries
|
|
if "zeitschrift_author[]" in form_data:
|
|
zeitschrift_authors = [
|
|
str(v) for v in form_data.getlist("zeitschrift_author[]")
|
|
]
|
|
zeitschrift_years = [str(v) for v in form_data.getlist("zeitschrift_year[]")]
|
|
zeitschrift_volumes = [
|
|
str(v) for v in form_data.getlist("zeitschrift_volume[]")
|
|
]
|
|
zeitschrift_article_titles = [
|
|
str(v) for v in form_data.getlist("zeitschrift_article_title[]")
|
|
]
|
|
zeitschrift_journal_titles = [
|
|
str(v) for v in form_data.getlist("zeitschrift_journal_title[]")
|
|
]
|
|
zeitschrift_signatures = [
|
|
str(v) for v in form_data.getlist("zeitschrift_signature[]")
|
|
]
|
|
zeitschrift_pages_from = [
|
|
str(v) for v in form_data.getlist("zeitschrift_pages_from[]")
|
|
]
|
|
zeitschrift_pages_to = [
|
|
str(v) for v in form_data.getlist("zeitschrift_pages_to[]")
|
|
]
|
|
|
|
zeitschrift_section = SubElement(media_root, "zeitschriftenartikel")
|
|
for i in range(len(zeitschrift_authors)):
|
|
entry = SubElement(zeitschrift_section, "entry")
|
|
SubElement(entry, "author").text = (
|
|
zeitschrift_authors[i] if i < len(zeitschrift_authors) else ""
|
|
)
|
|
SubElement(entry, "year").text = (
|
|
zeitschrift_years[i] if i < len(zeitschrift_years) else ""
|
|
)
|
|
SubElement(entry, "volume").text = (
|
|
zeitschrift_volumes[i] if i < len(zeitschrift_volumes) else ""
|
|
)
|
|
SubElement(entry, "article_title").text = (
|
|
zeitschrift_article_titles[i]
|
|
if i < len(zeitschrift_article_titles)
|
|
else ""
|
|
)
|
|
SubElement(entry, "journal_title").text = (
|
|
zeitschrift_journal_titles[i]
|
|
if i < len(zeitschrift_journal_titles)
|
|
else ""
|
|
)
|
|
SubElement(entry, "signature").text = (
|
|
zeitschrift_signatures[i] if i < len(zeitschrift_signatures) else ""
|
|
)
|
|
SubElement(entry, "pages_from").text = (
|
|
zeitschrift_pages_from[i] if i < len(zeitschrift_pages_from) else ""
|
|
)
|
|
SubElement(entry, "pages_to").text = (
|
|
zeitschrift_pages_to[i] if i < len(zeitschrift_pages_to) else ""
|
|
)
|
|
|
|
# Process Herausgeberwerk entries
|
|
if "herausgeber_publisher[]" in form_data:
|
|
herausgeber_publishers = [
|
|
str(v) for v in form_data.getlist("herausgeber_publisher[]")
|
|
]
|
|
herausgeber_work_titles = [
|
|
str(v) for v in form_data.getlist("herausgeber_work_title[]")
|
|
]
|
|
herausgeber_years = [str(v) for v in form_data.getlist("herausgeber_year[]")]
|
|
herausgeber_editions = [
|
|
str(v) for v in form_data.getlist("herausgeber_edition[]")
|
|
]
|
|
herausgeber_article_authors = [
|
|
str(v) for v in form_data.getlist("herausgeber_article_author[]")
|
|
]
|
|
herausgeber_article_titles = [
|
|
str(v) for v in form_data.getlist("herausgeber_article_title[]")
|
|
]
|
|
herausgeber_signatures = [
|
|
str(v) for v in form_data.getlist("herausgeber_signature[]")
|
|
]
|
|
herausgeber_pages_from = [
|
|
str(v) for v in form_data.getlist("herausgeber_pages_from[]")
|
|
]
|
|
herausgeber_pages_to = [
|
|
str(v) for v in form_data.getlist("herausgeber_pages_to[]")
|
|
]
|
|
|
|
herausgeber_section = SubElement(media_root, "herausgeberwerke")
|
|
for i in range(len(herausgeber_publishers)):
|
|
entry = SubElement(herausgeber_section, "entry")
|
|
SubElement(entry, "publisher").text = (
|
|
herausgeber_publishers[i] if i < len(herausgeber_publishers) else ""
|
|
)
|
|
SubElement(entry, "work_title").text = (
|
|
herausgeber_work_titles[i] if i < len(herausgeber_work_titles) else ""
|
|
)
|
|
SubElement(entry, "year").text = (
|
|
herausgeber_years[i] if i < len(herausgeber_years) else ""
|
|
)
|
|
SubElement(entry, "edition").text = (
|
|
herausgeber_editions[i] if i < len(herausgeber_editions) else ""
|
|
)
|
|
SubElement(entry, "article_author").text = (
|
|
herausgeber_article_authors[i]
|
|
if i < len(herausgeber_article_authors)
|
|
else ""
|
|
)
|
|
SubElement(entry, "article_title").text = (
|
|
herausgeber_article_titles[i]
|
|
if i < len(herausgeber_article_titles)
|
|
else ""
|
|
)
|
|
SubElement(entry, "signature").text = (
|
|
herausgeber_signatures[i] if i < len(herausgeber_signatures) else ""
|
|
)
|
|
SubElement(entry, "pages_from").text = (
|
|
herausgeber_pages_from[i] if i < len(herausgeber_pages_from) else ""
|
|
)
|
|
SubElement(entry, "pages_to").text = (
|
|
herausgeber_pages_to[i] if i < len(herausgeber_pages_to) else ""
|
|
)
|
|
|
|
xml_data = tostring(root, encoding="unicode")
|
|
|
|
# Send or print email
|
|
msg = MIMEText(xml_data, "xml")
|
|
msg["Subject"] = "New ELSA Form Submission"
|
|
msg["From"] = MAIL_FROM
|
|
msg["To"] = MAIL_TO
|
|
|
|
if MAIL_ENABLED:
|
|
with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server:
|
|
server.send_message(msg)
|
|
else:
|
|
print("=" * 80)
|
|
print("MAIL SENDING DISABLED - Would have sent:")
|
|
print(f"From: {MAIL_FROM}")
|
|
print(f"To: {MAIL_TO}")
|
|
print(f"Subject: {msg['Subject']}")
|
|
print("-" * 80)
|
|
print(xml_data)
|
|
print("=" * 80)
|
|
|
|
return RedirectResponse("/?success=true", status_code=303)
|