diff options
| author | herkulessi <git@herkulessi.de> | 2026-07-04 20:39:51 +0200 |
|---|---|---|
| committer | herkulessi <git@herkulessi.de> | 2026-07-04 20:39:51 +0200 |
| commit | accc7d850319324336836b62bd4309469c0d26f1 (patch) | |
| tree | a45a3c7a4e8e4b5793d624d24c5366de72ec5ff2 /main.go | |
Initial Commit
Diffstat (limited to 'main.go')
| -rw-r--r-- | main.go | 136 |
1 files changed, 136 insertions, 0 deletions
@@ -0,0 +1,136 @@ +package main + +import ( + _ "embed" + "encoding/gob" + "io" + "log/slog" + "net/http" + "net/url" + "os" + "strings" + "sync" +) + +//go:embed popup.html +var popup string + +//go:embed notfound.html +var notfound string + +//go:embed genericerror.html +var genericerror string + +var migratedLock = sync.RWMutex{} +var migrated = map[string]struct{}{} + +func migrate(id string) { + migratedLock.Lock() + migrated[id] = struct{}{} + migratedLock.Unlock() + slog.Info("Saving migrations", "id", id) + save() +} +func save() { + file, err := os.Create("migrated") + if err != nil { + slog.Warn("Could not create Migration-File", "err", err) + return + } + defer file.Close() + enc := gob.NewEncoder(file) + migratedLock.RLock() + defer migratedLock.RUnlock() + err = enc.Encode(migrated) + if err != nil { + slog.Warn("Could not encode migrations", "err", err) + return + } +} + +func main() { + file, err := os.Open("migrated") + if err != nil { + slog.Warn("Could not open migration history", "err", err) + save() + } else { + dec := gob.NewDecoder(file) + dec.Decode(&migrated) + } + + http.HandleFunc("GET /p/{id}", func(w http.ResponseWriter, r *http.Request) { + id := url.PathEscape(r.PathValue("id")) + + migratedLock.RLock() + if _, ok := migrated[id]; ok { + migratedLock.RUnlock() + http.Redirect(w, r, "https://notes.stuve.fau.de/stuve-etherpad-migrated-"+id, 302) + return + } + migratedLock.RUnlock() + + req, err := http.Get("http://127.0.0.1:9001/p/" + id + "/export/html") + if err != nil { + w.WriteHeader(502) + slog.Error("Could not fetch Pad as html", "err", err, "id", id) + w.Write([]byte(genericerror)) + return + } + defer req.Body.Close() + if req.StatusCode == 404 { + w.WriteHeader(404) + slog.Error("Could not fetch Pad: 404", "id", id) + w.Write([]byte(notfound)) + return + } + body, err := io.ReadAll(req.Body) + if req.StatusCode != 200 { + w.WriteHeader(req.StatusCode) + slog.Error("Could not fetch Pad", "id", id, "status", req.Status, "body", string(body)) + w.Write([]byte(genericerror)) + return + } + if err != nil { + w.WriteHeader(502) + slog.Error("Could not read entire body", "err", err, "id", id) + w.Write([]byte(genericerror)) + return + } + w.Write([]byte(strings.Replace(string(body), "<body>", popup, 1))) + }) + http.HandleFunc("POST /p/{id}", func(w http.ResponseWriter, r *http.Request) { + id := r.PathValue("id") + req, err := http.Get("http://127.0.0.1:9001/p/" + id + "/export/markdown") + if err != nil { + w.WriteHeader(502) + slog.Error("Could not fetch Pad as markdown", "err", err, "id", id) + w.Write([]byte(genericerror)) + return + } + if req.StatusCode == 404 { + w.WriteHeader(404) + slog.Error("Could not fetch Pad: 404", "id", id) + w.Write([]byte(notfound)) + return + } + if req.StatusCode != 200 { + body, err := io.ReadAll(req.Body) + w.WriteHeader(req.StatusCode) + slog.Error("Could not fetch Pad", "id", id, "status", req.Status, "body", string(body), "err", err) + w.Write([]byte(genericerror)) + return + } + resp, err := http.Post("https://notes.stuve.fau.de/new/stuve-etherpad-migrated-"+id, "text/markdown", req.Body) + if resp.StatusCode != 200 { + body, err := io.ReadAll(resp.Body) + w.WriteHeader(req.StatusCode) + slog.Error("Could not Post Pad", "id", id, "status", req.Status, "body", string(body), "err", err) + w.Write([]byte(genericerror)) + return + } + migrate(id) + http.Redirect(w, r, "https://notes.stuve.fau.de/stuve-etherpad-migrated-"+id, 302) + }) + err = http.ListenAndServe("[::]:8080", nil) + panic(err) +} |
