diff --git a/misc/misc.go b/misc/misc.go
new file mode 100644
index 0000000..2f9b44e
--- /dev/null
+++ b/misc/misc.go
@@ -0,0 +1,111 @@
+// Package misc provides miscellaneous informative views.
+package misc
+
+import (
+ "github.com/bouncepaw/mycorrhiza/cfg"
+ "github.com/bouncepaw/mycorrhiza/files"
+ "github.com/bouncepaw/mycorrhiza/hyphae"
+ "github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
+ "github.com/bouncepaw/mycorrhiza/l18n"
+ "github.com/bouncepaw/mycorrhiza/shroom"
+ "github.com/bouncepaw/mycorrhiza/user"
+ "github.com/bouncepaw/mycorrhiza/util"
+ "github.com/bouncepaw/mycorrhiza/views"
+ "github.com/bouncepaw/mycorrhiza/viewutil"
+ "github.com/gorilla/mux"
+ "io"
+ "log"
+ "math/rand"
+ "net/http"
+)
+
+func InitHandlers(rtr *mux.Router) {
+ rtr.HandleFunc("/list", handlerList)
+ rtr.HandleFunc("/reindex", handlerReindex)
+ rtr.HandleFunc("/update-header-links", handlerUpdateHeaderLinks)
+ rtr.HandleFunc("/random", handlerRandom)
+ rtr.HandleFunc("/about", handlerAbout)
+ rtr.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) {
+ http.Redirect(w, rq, "/static/favicon.ico", http.StatusSeeOther)
+ })
+}
+
+// handlerList shows a list of all hyphae in the wiki in random order.
+func handlerList(w http.ResponseWriter, rq *http.Request) {
+ var lc = l18n.FromRequest(rq)
+ util.PrepareRq(rq)
+ util.HTTP200Page(w, views.Base(
+ viewutil.MetaFrom(w, rq),
+ lc.Get("ui.list_title"),
+ views.HyphaList(lc),
+ ))
+}
+
+// handlerReindex reindexes all hyphae by checking the wiki storage directory anew.
+func handlerReindex(w http.ResponseWriter, rq *http.Request) {
+ util.PrepareRq(rq)
+ if ok := user.CanProceed(rq, "reindex"); !ok {
+ var lc = l18n.FromRequest(rq)
+ viewutil.HttpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.reindex_no_rights"))
+ log.Println("Rejected", rq.URL)
+ return
+ }
+ hyphae.ResetCount()
+ log.Println("Reindexing hyphae in", files.HyphaeDir())
+ hyphae.Index(files.HyphaeDir())
+ backlinks.IndexBacklinks()
+ http.Redirect(w, rq, "/", http.StatusSeeOther)
+}
+
+// handlerUpdateHeaderLinks updates header links by reading the configured hypha, if there is any, or resorting to default values.
+func handlerUpdateHeaderLinks(w http.ResponseWriter, rq *http.Request) {
+ util.PrepareRq(rq)
+ if ok := user.CanProceed(rq, "update-header-links"); !ok {
+ var lc = l18n.FromRequest(rq)
+ viewutil.HttpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.header_no_rights"))
+ log.Println("Rejected", rq.URL)
+ return
+ }
+ shroom.SetHeaderLinks()
+ http.Redirect(w, rq, "/", http.StatusSeeOther)
+}
+
+// handlerRandom redirects to a random hypha.
+func handlerRandom(w http.ResponseWriter, rq *http.Request) {
+ util.PrepareRq(rq)
+ var (
+ randomHyphaName string
+ amountOfHyphae = hyphae.Count()
+ )
+ if amountOfHyphae == 0 {
+ var lc = l18n.FromRequest(rq)
+ viewutil.HttpErr(viewutil.MetaFrom(w, rq), lc, http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae_tip"))
+ return
+ }
+ i := rand.Intn(amountOfHyphae)
+ for h := range hyphae.YieldExistingHyphae() {
+ if i == 0 {
+ randomHyphaName = h.CanonicalName()
+ }
+ i--
+ }
+ http.Redirect(w, rq, "/hypha/"+randomHyphaName, http.StatusSeeOther)
+}
+
+// handlerAbout shows a summary of wiki's software.
+func handlerAbout(w http.ResponseWriter, rq *http.Request) {
+ w.Header().Set("Content-Type", "text/html;charset=utf-8")
+ w.WriteHeader(http.StatusOK)
+ var (
+ lc = l18n.FromRequest(rq)
+ title = lc.Get("ui.about_title", &l18n.Replacements{"name": cfg.WikiName})
+ )
+ _, err := io.WriteString(w, views.Base(
+ viewutil.MetaFrom(w, rq),
+ title,
+ views.AboutHTML(lc),
+ ))
+ if err != nil {
+ log.Println(err)
+ }
+}
diff --git a/viewutil/err.go b/viewutil/err.go
new file mode 100644
index 0000000..200233e
--- /dev/null
+++ b/viewutil/err.go
@@ -0,0 +1,28 @@
+package viewutil
+
+import (
+ "fmt"
+ "github.com/bouncepaw/mycorrhiza/l18n"
+ "mime"
+ "net/http"
+)
+
+// HttpErr is used by many handlers to signal errors in a compact way.
+// TODO: get rid of this abomination
+func HttpErr(meta Meta, lc *l18n.Localizer, status int, name, errMsg string) {
+ meta.W.(http.ResponseWriter).Header().Set("Content-Type", mime.TypeByExtension(".html"))
+ meta.W.(http.ResponseWriter).WriteHeader(status)
+ fmt.Fprint(
+ meta.W,
+ Base(
+ meta,
+ "Error",
+ fmt.Sprintf(
+ `%s. %s
`,
+ errMsg,
+ name,
+ lc.Get("ui.error_go_back"),
+ ),
+ ),
+ )
+}
diff --git a/web/mutators.go b/web/mutators.go
index d14cb4c..0737e69 100644
--- a/web/mutators.go
+++ b/web/mutators.go
@@ -39,7 +39,7 @@ func handlerRemoveMedia(w http.ResponseWriter, rq *http.Request) {
meta = viewutil.MetaFrom(w, rq)
)
if !u.CanProceed("remove-media") {
- httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no rights")
+ viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no rights")
return
}
if rq.Method == "GET" {
@@ -53,11 +53,11 @@ func handlerRemoveMedia(w http.ResponseWriter, rq *http.Request) {
}
switch h := h.(type) {
case *hyphae.EmptyHypha, *hyphae.TextualHypha:
- httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no media to remove")
+ viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no media to remove")
return
case *hyphae.MediaHypha:
if err := shroom.RemoveMedia(u, h); err != nil {
- httpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error())
+ viewutil.HttpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error())
return
}
}
@@ -74,7 +74,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) {
if !u.CanProceed("delete") {
log.Printf("%s has no rights to delete ‘%s’\n", u.Name, h.CanonicalName())
- httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights")
+ viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights")
return
}
@@ -82,7 +82,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) {
case *hyphae.EmptyHypha:
log.Printf("%s tries to delete empty hypha ‘%s’\n", u.Name, h.CanonicalName())
// TODO: localize
- httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha")
+ viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha")
return
}
@@ -98,7 +98,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) {
if err := shroom.Delete(u, h.(hyphae.ExistingHypha)); err != nil {
log.Println(err)
- httpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error())
+ viewutil.HttpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error())
return
}
http.Redirect(w, rq, "/hypha/"+h.CanonicalName(), http.StatusSeeOther)
@@ -116,13 +116,13 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) {
switch h.(type) {
case *hyphae.EmptyHypha:
log.Printf("%s tries to rename empty hypha ‘%s’", u.Name, h.CanonicalName())
- httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize
+ viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize
return
}
if !u.CanProceed("rename") {
log.Printf("%s has no rights to rename ‘%s’\n", u.Name, h.CanonicalName())
- httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights")
+ viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights")
return
}
@@ -144,7 +144,7 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) {
if err := shroom.Rename(oldHypha, newName, recursive, u); err != nil {
log.Printf("%s tries to rename ‘%s’: %s", u.Name, oldHypha.CanonicalName(), err.Error())
- httpErr(meta, lc, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize
+ viewutil.HttpErr(meta, lc, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize
return
}
http.Redirect(w, rq, "/hypha/"+newName, http.StatusSeeOther)
@@ -164,7 +164,7 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) {
meta = viewutil.MetaFrom(w, rq)
)
if err := shroom.CanEdit(u, h, lc); err != nil {
- httpErr(meta, lc, http.StatusInternalServerError, hyphaName,
+ viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName,
err.Error())
return
}
@@ -175,7 +175,7 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) {
textAreaFill, err = shroom.FetchTextFile(h)
if err != nil {
log.Println(err)
- httpErr(meta, lc, http.StatusInternalServerError, hyphaName,
+ viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName,
lc.Get("ui.error_text_fetch"))
return
}
@@ -204,7 +204,7 @@ func handlerUploadText(w http.ResponseWriter, rq *http.Request) {
if action != "Preview" {
if err := shroom.UploadText(h, []byte(textData), message, u); err != nil {
- httpErr(meta, lc, http.StatusForbidden, hyphaName, err.Error())
+ viewutil.HttpErr(meta, lc, http.StatusForbidden, hyphaName, err.Error())
return
}
}
@@ -242,11 +242,11 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) {
meta = viewutil.MetaFrom(w, rq)
)
if err != nil {
- httpErr(meta, lc, http.StatusInternalServerError, hyphaName,
+ viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName,
err.Error())
}
if err := shroom.CanAttach(u, h, lc); err != nil {
- httpErr(meta, lc, http.StatusInternalServerError, hyphaName,
+ viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName,
err.Error())
}
@@ -265,7 +265,7 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) {
)
if err := shroom.UploadBinary(h, mime, file, u); err != nil {
- httpErr(meta, lc, http.StatusInternalServerError, hyphaName, err.Error())
+ viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, err.Error())
return
}
http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther)
diff --git a/web/stuff.go b/web/stuff.go
index f43c387..71eb1f7 100644
--- a/web/stuff.go
+++ b/web/stuff.go
@@ -2,24 +2,15 @@ package web
// stuff.go is used for meta stuff about the wiki or all hyphae at once.
import (
- "github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
"github.com/bouncepaw/mycorrhiza/viewutil"
"io"
- "log"
- "math/rand"
"net/http"
"strings"
"github.com/gorilla/mux"
- "github.com/bouncepaw/mycorrhiza/cfg"
- "github.com/bouncepaw/mycorrhiza/files"
"github.com/bouncepaw/mycorrhiza/help"
- "github.com/bouncepaw/mycorrhiza/hyphae"
"github.com/bouncepaw/mycorrhiza/l18n"
- "github.com/bouncepaw/mycorrhiza/shroom"
- "github.com/bouncepaw/mycorrhiza/user"
- "github.com/bouncepaw/mycorrhiza/util"
"github.com/bouncepaw/mycorrhiza/views"
"github.com/bouncepaw/mycomarkup/v3"
@@ -28,14 +19,6 @@ import (
func initStuff(r *mux.Router) {
r.PathPrefix("/help").HandlerFunc(handlerHelp)
- r.HandleFunc("/list", handlerList)
- r.HandleFunc("/reindex", handlerReindex)
- r.HandleFunc("/update-header-links", handlerUpdateHeaderLinks)
- r.HandleFunc("/random", handlerRandom)
- r.HandleFunc("/about", handlerAbout)
- r.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) {
- http.Redirect(w, rq, "/static/favicon.ico", http.StatusSeeOther)
- })
}
// handlerHelp gets the appropriate documentation or tells you where you (personally) have failed.
@@ -94,85 +77,3 @@ func handlerHelp(w http.ResponseWriter, rq *http.Request) {
),
)
}
-
-// handlerList shows a list of all hyphae in the wiki in random order.
-func handlerList(w http.ResponseWriter, rq *http.Request) {
- var lc = l18n.FromRequest(rq)
- util.PrepareRq(rq)
- util.HTTP200Page(w, views.Base(
- viewutil.MetaFrom(w, rq),
- lc.Get("ui.list_title"),
- views.HyphaList(lc),
- ))
-}
-
-// handlerReindex reindexes all hyphae by checking the wiki storage directory anew.
-func handlerReindex(w http.ResponseWriter, rq *http.Request) {
- util.PrepareRq(rq)
- if ok := user.CanProceed(rq, "reindex"); !ok {
- var lc = l18n.FromRequest(rq)
- httpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.reindex_no_rights"))
- log.Println("Rejected", rq.URL)
- return
- }
- hyphae.ResetCount()
- log.Println("Reindexing hyphae in", files.HyphaeDir())
- hyphae.Index(files.HyphaeDir())
- backlinks.IndexBacklinks()
- http.Redirect(w, rq, "/", http.StatusSeeOther)
-}
-
-// handlerUpdateHeaderLinks updates header links by reading the configured hypha, if there is any, or resorting to default values.
-//
-// See https://mycorrhiza.wiki/hypha/configuration/header
-func handlerUpdateHeaderLinks(w http.ResponseWriter, rq *http.Request) {
- util.PrepareRq(rq)
- if ok := user.CanProceed(rq, "update-header-links"); !ok {
- var lc = l18n.FromRequest(rq)
- httpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.header_no_rights"))
- log.Println("Rejected", rq.URL)
- return
- }
- shroom.SetHeaderLinks()
- http.Redirect(w, rq, "/", http.StatusSeeOther)
-}
-
-// handlerRandom redirects to a random hypha.
-func handlerRandom(w http.ResponseWriter, rq *http.Request) {
- util.PrepareRq(rq)
- var (
- randomHyphaName string
- amountOfHyphae = hyphae.Count()
- )
- if amountOfHyphae == 0 {
- var lc = l18n.FromRequest(rq)
- httpErr(viewutil.MetaFrom(w, rq), lc, http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae_tip"))
- return
- }
- i := rand.Intn(amountOfHyphae)
- for h := range hyphae.YieldExistingHyphae() {
- if i == 0 {
- randomHyphaName = h.CanonicalName()
- }
- i--
- }
- http.Redirect(w, rq, "/hypha/"+randomHyphaName, http.StatusSeeOther)
-}
-
-// handlerAbout shows a summary of wiki's software.
-func handlerAbout(w http.ResponseWriter, rq *http.Request) {
- w.Header().Set("Content-Type", "text/html;charset=utf-8")
- w.WriteHeader(http.StatusOK)
- var (
- lc = l18n.FromRequest(rq)
- title = lc.Get("ui.about_title", &l18n.Replacements{"name": cfg.WikiName})
- )
- _, err := io.WriteString(w, views.Base(
- viewutil.MetaFrom(w, rq),
- title,
- views.AboutHTML(lc),
- ))
- if err != nil {
- log.Println(err)
- }
-}
diff --git a/web/web.go b/web/web.go
index 04a1cbd..0686cb2 100644
--- a/web/web.go
+++ b/web/web.go
@@ -2,8 +2,8 @@
package web
import (
- "fmt"
"github.com/bouncepaw/mycorrhiza/categories"
+ "github.com/bouncepaw/mycorrhiza/misc"
"github.com/bouncepaw/mycorrhiza/viewutil"
"io"
"mime"
@@ -22,26 +22,6 @@ import (
var stylesheets = []string{"default.css", "custom.css"}
-// httpErr is used by many handlers to signal errors in a compact way.
-// TODO: get rid of this abomination
-func httpErr(meta viewutil.Meta, lc *l18n.Localizer, status int, name, errMsg string) {
- meta.W.(http.ResponseWriter).Header().Set("Content-Type", mime.TypeByExtension(".html"))
- meta.W.(http.ResponseWriter).WriteHeader(status)
- fmt.Fprint(
- meta.W,
- views.Base(
- meta,
- "Error",
- fmt.Sprintf(
- `%s. %s
`,
- errMsg,
- name,
- lc.Get("ui.error_go_back"),
- ),
- ),
- )
-}
-
func handlerStyle(w http.ResponseWriter, rq *http.Request) {
w.Header().Set("Content-Type", mime.TypeByExtension(".css"))
for _, name := range stylesheets {
@@ -111,6 +91,7 @@ func Handler() http.Handler {
initSearch(wikiRouter)
initBacklinks(wikiRouter)
categories.InitHandlers(wikiRouter)
+ misc.InitHandlers(wikiRouter)
// Admin routes.
if cfg.UseAuth {