feat(aether): initial commit – self-hosted Cloud, Phasen 1–7
Go-Backend (chi, pgx, golang-migrate) + React/TS-Frontend als PWA. Enthalten: Auth inkl. OIDC, Dateien mit Versionen und Papierkorb, Freigaben (Links + intern), WebDAV, Gruppenordner, Admin/Theming, Volltextsuche mit OCR, eigener PDF-Betrachter und WOPI-Office (Collabora/OnlyOffice). Nicht im Repo: deploy/.env (Sitzungsschlüssel, DB- und Admin-Passwort) sowie alle Daten- und Build-Verzeichnisse – siehe .gitignore. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
commit
31a027c93a
225 files changed
+38042
No files matched your search
@@ -0,0 +1,50 @@
|
||||
package files
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"aether/pkg/response"
|
||||
)
|
||||
|
||||
// TextPages beantwortet GET /api/v1/files/{id}/text.
|
||||
//
|
||||
// **Wofür das da ist:** Der PDF-Betrachter im Browser sucht im Dokument – aber
|
||||
// bei einem *Scan* steht im PDF kein einziges Wort, nur ein Bild. Der erkannte
|
||||
// Text liegt daneben in der Datenbank. Ohne diesen Endpunkt fände die Suche im
|
||||
// Dokument ausgerechnet bei dem Dateityp nichts, für den die Texterkennung
|
||||
// überhaupt gebaut wurde.
|
||||
//
|
||||
// Geliefert wird der Text **in Seiten zerlegt**. Mehr geht nicht: Wo genau auf
|
||||
// dem Bild ein Wort steht, weiß nur die Erkennung selbst, und wir bewahren
|
||||
// ihre Koordinaten nicht auf. Die Seite ist aber der Sprung, auf den es
|
||||
// ankommt – bei einem zwölfseitigen Beleg ist das der Unterschied zwischen
|
||||
// „gefunden" und „such weiter".
|
||||
//
|
||||
// Die Prüfung ist dieselbe wie beim Herunterladen: Wer die Datei nicht lesen
|
||||
// darf, bekommt hier auch ihren Text nicht. Das ist keine Kleinigkeit – der
|
||||
// Text *ist* der Inhalt der Rechnung.
|
||||
func (h *Handler) TextPages(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := parseID(r, "id")
|
||||
if err != nil {
|
||||
response.Error(w, http.StatusBadRequest, "invalid file id")
|
||||
return
|
||||
}
|
||||
if _, ok := h.resolveFile(w, r, id, false); !ok {
|
||||
return
|
||||
}
|
||||
// Ohne Texterkennung gibt es keinen Text – das ist eine Auskunft, kein
|
||||
// Fehler. Der Betrachter zeigt dann schlicht keine Fundstellen an.
|
||||
if h.docs == nil {
|
||||
response.JSON(w, http.StatusOK, map[string]any{"pages": []string{}, "source": ""})
|
||||
return
|
||||
}
|
||||
pages, source, err := h.docs.TextPages(r.Context(), id)
|
||||
if err != nil {
|
||||
response.Error(w, http.StatusInternalServerError, "database error")
|
||||
return
|
||||
}
|
||||
if pages == nil {
|
||||
pages = []string{}
|
||||
}
|
||||
response.JSON(w, http.StatusOK, map[string]any{"pages": pages, "source": source})
|
||||
}
|
||||
Reference in new issue
Block a user