package views import ( "log" "net/http" "os" "path" "path/filepath" "strconv" "strings" urls "forgejo.gwairfelin.com/max/gispatcho" "forgejo.gwairfelin.com/max/gonotes/internal/conf" "forgejo.gwairfelin.com/max/gonotes/internal/middleware" "forgejo.gwairfelin.com/max/gonotes/internal/notes" "forgejo.gwairfelin.com/max/gonotes/internal/templ" ) var myurls urls.URLs func addRequestContext(r *http.Request, ctx templ.Ctx) templ.Ctx { return ctx } func GetRoutes(prefix string) *http.ServeMux { myurls = urls.URLs{ Prefix: prefix, URLs: map[string]urls.URL{ "list": {Path: "/", Protocol: "GET", Handler: list}, "new": {Path: "/new", Protocol: "GET", Handler: new}, "view_": {Path: "/{note}", Protocol: "GET", Handler: view}, "view": {Path: "/{note}/", Protocol: "GET", Handler: view}, "delete": {Path: "/{note}/delete/", Protocol: "GET", Handler: delete}, "edit": {Path: "/{note}/edit/", Protocol: "GET", Handler: edit}, "save": {Path: "/{note}/edit/save/", Protocol: "POST", Handler: save}, "togglebox": {Path: "/{note}/togglebox/", Protocol: "POST", Handler: togglebox}, }, } return myurls.GetRouter() } func view(w http.ResponseWriter, r *http.Request) { user := r.Context().Value(middleware.ContextKey("user")).(string) title := r.PathValue("note") note, err := notes.LoadNote(user, title) urlEdit := myurls.Reverse("edit", urls.Repl{"note": title}) urlDelete := myurls.Reverse("delete", urls.Repl{"note": title}) if err != nil { http.Redirect(w, r, urlEdit, http.StatusFound) return } context := templ.Ctx{"note": note, "urlEdit": urlEdit, "urlDelete": urlDelete} note.Render() err = templ.RenderTemplate(w, r, "view.tmpl.html", context) if err != nil { log.Print(err.Error()) http.Error(w, "Couldn't load template", http.StatusInternalServerError) return } } func edit(w http.ResponseWriter, r *http.Request) { user := r.Context().Value(middleware.ContextKey("user")).(string) encodedTitle := r.PathValue("note") note, err := notes.LoadNote(user, encodedTitle) if err != nil { title := notes.DecodeTitle(encodedTitle) note = ¬es.Note{Title: title} } urlSave := myurls.Reverse("save", urls.Repl{"note": encodedTitle}) context := templ.Ctx{"note": note, "urlSave": urlSave, "text": string(note.Body)} err = templ.RenderTemplate(w, r, "edit.tmpl.html", context) if err != nil { log.Print(err.Error()) http.Error(w, "Couldn't load template", http.StatusInternalServerError) return } } func new(w http.ResponseWriter, r *http.Request) { title := r.FormValue("title") if len(title) == 0 { title = "" } note := ¬es.Note{Title: title} urlEdit := myurls.Reverse("edit", urls.Repl{"note": note.EncodedTitle()}) http.Redirect(w, r, urlEdit, http.StatusFound) } func delete(w http.ResponseWriter, r *http.Request) { user := r.Context().Value(middleware.ContextKey("user")).(string) encodedTitle := r.PathValue("note") err := notes.DeleteNote(user, encodedTitle) if err != nil { log.Print(err.Error()) http.Error(w, "Couldn't delete note", http.StatusInternalServerError) return } urlList := myurls.Reverse("list", urls.Repl{}) http.Redirect(w, r, urlList, http.StatusFound) } func save(w http.ResponseWriter, r *http.Request) { user := r.Context().Value(middleware.ContextKey("user")).(string) oldTitle := r.PathValue("note") title := r.FormValue("title") body := r.FormValue("body") note := ¬es.Note{Title: title, Body: []byte(body), Owner: user} note.Save() if oldTitle != note.EncodedTitle() { notes.DeleteNote(user, oldTitle) } http.Redirect(w, r, myurls.Reverse("view", urls.Repl{"note": note.EncodedTitle()}), http.StatusFound) } func togglebox(w http.ResponseWriter, r *http.Request) { user := r.Context().Value(middleware.ContextKey("user")).(string) title := r.PathValue("note") nthBox, err := strconv.Atoi(r.FormValue("box")) if err != nil { log.Fatal("You fucked up boy") return } note, err := notes.LoadNote(user, title) if err != nil { http.Redirect(w, r, myurls.Reverse("view", urls.Repl{"note": title}), http.StatusFound) return } note.ToggleBox(nthBox) http.Redirect(w, r, myurls.Reverse("view", urls.Repl{"note": note.EncodedTitle()}), http.StatusFound) } type titleAndURL struct { Title string URL string } func list(w http.ResponseWriter, r *http.Request) { user := r.Context().Value(middleware.ContextKey("user")).(string) notesDir := path.Join(conf.Conf.NotesDir, user) files, err := os.ReadDir(notesDir) if err != nil { if os.IsNotExist(err) { os.MkdirAll(notesDir, os.FileMode(0750)) } else { log.Print(err.Error()) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } } titlesAndUrls := make([]titleAndURL, 0) for _, f := range files { if !f.IsDir() { encodedTitle := strings.TrimSuffix(f.Name(), filepath.Ext(f.Name())) title := notes.DecodeTitle(encodedTitle) log.Printf("Found note %s (title '%s')", encodedTitle, title) titlesAndUrls = append( titlesAndUrls, titleAndURL{Title: title, URL: myurls.Reverse("view", urls.Repl{"note": encodedTitle})}, ) log.Print(titlesAndUrls) } } urlNew := myurls.Reverse("new", urls.Repl{}) err = templ.RenderTemplate(w, r, "list.tmpl.html", templ.Ctx{"notes": titlesAndUrls, "urlNew": urlNew}) if err != nil { log.Print(err.Error()) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } }