summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go136
1 files changed, 136 insertions, 0 deletions
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..cd8c20f
--- /dev/null
+++ b/main.go
@@ -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)
+}