1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-12-12 05:20:26 +00:00
mycorrhiza/main.go

203 lines
6.2 KiB
Go
Raw Normal View History

2020-08-31 17:52:26 +00:00
//go:generate go get -u github.com/valyala/quicktemplate/qtc
//go:generate qtc -dir=assets
//go:generate qtc -dir=views
2020-06-12 16:22:02 +00:00
package main
import (
"fmt"
2020-12-15 18:59:36 +00:00
"io/ioutil"
2020-06-13 11:18:11 +00:00
"log"
2020-08-31 18:35:36 +00:00
"math/rand"
2020-06-13 11:18:11 +00:00
"net/http"
2020-06-12 16:22:02 +00:00
"os"
2020-12-15 18:59:36 +00:00
"strings"
2020-08-08 20:10:28 +00:00
"github.com/bouncepaw/mycorrhiza/assets"
2020-08-08 20:10:28 +00:00
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/hyphae"
2021-02-20 14:03:54 +00:00
"github.com/bouncepaw/mycorrhiza/shroom"
"github.com/bouncepaw/mycorrhiza/user"
"github.com/bouncepaw/mycorrhiza/util"
"github.com/bouncepaw/mycorrhiza/views"
2020-06-12 16:22:02 +00:00
)
// WikiDir is a rooted path to the wiki storage directory.
var WikiDir string
// HttpErr is used by many handlers to signal errors in a compact way.
func HttpErr(w http.ResponseWriter, status int, name, title, errMsg string) {
log.Println(errMsg, "for", name)
w.Header().Set("Content-Type", "text/html;charset=utf-8")
w.WriteHeader(status)
2021-01-24 07:30:14 +00:00
fmt.Fprint(
w,
base(
title,
fmt.Sprintf(
2021-02-19 16:56:31 +00:00
`<main class="main-width"><p>%s. <a href="/page/%s">Go back to the hypha.<a></p></main>`,
2021-01-24 07:30:14 +00:00
errMsg,
name,
),
user.EmptyUser(),
),
)
}
// Show all hyphae
func handlerList(w http.ResponseWriter, rq *http.Request) {
log.Println(rq.URL)
2021-02-22 18:37:23 +00:00
util.HTTP200Page(w, base("List of pages", views.HyphaListHTML(), user.FromRequest(rq)))
}
// This part is present in all html documents.
var base = views.BaseHTML
// Reindex all hyphae by checking the wiki storage directory anew.
func handlerReindex(w http.ResponseWriter, rq *http.Request) {
log.Println(rq.URL)
if ok := user.CanProceed(rq, "reindex"); !ok {
HttpErr(w, http.StatusForbidden, util.HomePage, "Not enough rights", "You must be an admin to reindex hyphae.")
log.Println("Rejected", rq.URL)
return
}
hyphae.ResetCount()
log.Println("Wiki storage directory is", WikiDir)
log.Println("Start indexing hyphae...")
2021-02-17 18:41:35 +00:00
hyphae.Index(WikiDir)
log.Println("Indexed", hyphae.Count(), "hyphae")
2021-01-23 19:00:58 +00:00
http.Redirect(w, rq, "/", http.StatusSeeOther)
}
2021-02-18 14:50:37 +00:00
// Stop the wiki
2021-01-23 19:00:58 +00:00
// Update header links by reading the configured hypha, if there is any, or resorting to default values.
func handlerUpdateHeaderLinks(w http.ResponseWriter, rq *http.Request) {
log.Println(rq.URL)
if ok := user.CanProceed(rq, "update-header-links"); !ok {
HttpErr(w, http.StatusForbidden, util.HomePage, "Not enough rights", "You must be a moderator to update header links.")
log.Println("Rejected", rq.URL)
return
}
2021-02-20 14:03:54 +00:00
shroom.SetHeaderLinks()
2021-01-23 19:00:58 +00:00
http.Redirect(w, rq, "/", http.StatusSeeOther)
}
2020-08-31 18:35:36 +00:00
// Redirect to a random hypha.
func handlerRandom(w http.ResponseWriter, rq *http.Request) {
log.Println(rq.URL)
var randomHyphaName string
i := rand.Intn(hyphae.Count())
2021-02-17 18:41:35 +00:00
for h := range hyphae.YieldExistingHyphae() {
2020-08-31 18:35:36 +00:00
if i == 0 {
2021-02-17 18:41:35 +00:00
randomHyphaName = h.Name
2020-08-31 18:35:36 +00:00
}
i--
}
2021-02-17 18:41:35 +00:00
http.Redirect(w, rq, "/hypha/"+randomHyphaName, http.StatusSeeOther)
2020-08-31 18:35:36 +00:00
}
2020-10-25 18:02:52 +00:00
func handlerStyle(w http.ResponseWriter, rq *http.Request) {
log.Println(rq.URL)
if _, err := os.Stat(util.WikiDir + "/static/common.css"); err == nil {
http.ServeFile(w, rq, util.WikiDir+"/static/common.css")
2020-10-25 18:02:52 +00:00
} else {
w.Header().Set("Content-Type", "text/css;charset=utf-8")
w.Write([]byte(assets.DefaultCSS()))
2020-10-25 18:02:52 +00:00
}
if bytes, err := ioutil.ReadFile(util.WikiDir + "/static/custom.css"); err == nil {
w.Write(bytes)
}
2020-10-25 18:02:52 +00:00
}
2020-12-15 18:59:36 +00:00
func handlerIcon(w http.ResponseWriter, rq *http.Request) {
iconName := strings.TrimPrefix(rq.URL.Path, "/static/icon/")
if iconName == "https" {
iconName = "http"
}
files, err := ioutil.ReadDir(WikiDir + "/static/icon")
if err == nil {
for _, f := range files {
if strings.HasPrefix(f.Name(), iconName+"-protocol-icon") {
http.ServeFile(w, rq, WikiDir+"/static/icon/"+f.Name())
return
}
}
}
w.Header().Set("Content-Type", "image/svg+xml")
switch iconName {
case "gemini":
w.Write([]byte(assets.IconGemini()))
2020-12-15 18:59:36 +00:00
case "mailto":
w.Write([]byte(assets.IconMailto()))
2020-12-15 18:59:36 +00:00
case "gopher":
w.Write([]byte(assets.IconGopher()))
2020-12-15 18:59:36 +00:00
default:
w.Write([]byte(assets.IconHTTP()))
2020-12-15 18:59:36 +00:00
}
}
func handlerAbout(w http.ResponseWriter, rq *http.Request) {
w.Header().Set("Content-Type", "text/html;charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Write([]byte(base("About "+util.SiteName, views.AboutHTML(), user.FromRequest(rq))))
}
2021-01-30 18:21:50 +00:00
func handlerUserList(w http.ResponseWriter, rq *http.Request) {
w.Header().Set("Content-Type", "text/html;charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Write([]byte(base("User list", views.UserListHTML(), user.FromRequest(rq))))
2021-01-30 18:21:50 +00:00
}
2020-12-29 08:10:11 +00:00
func handlerRobotsTxt(w http.ResponseWriter, rq *http.Request) {
w.Header().Set("Content-Type", "text/plain")
w.WriteHeader(http.StatusOK)
w.Write([]byte(
`User-agent: *
Allow: /page/
Allow: /recent-changes
Disallow: /
Crawl-delay: 5`))
}
func main() {
log.Println("Running MycorrhizaWiki β")
2020-10-25 15:06:51 +00:00
parseCliArgs()
2020-08-19 18:54:23 +00:00
if err := os.Chdir(WikiDir); err != nil {
log.Fatal(err)
}
log.Println("Wiki storage directory is", WikiDir)
2021-02-17 18:41:35 +00:00
hyphae.Index(WikiDir)
log.Println("Indexed", hyphae.Count(), "hyphae")
2021-02-20 14:03:54 +00:00
shroom.FindAllBacklinks()
2021-02-19 09:23:57 +00:00
log.Println("Found all backlinks")
2020-08-08 20:10:28 +00:00
history.Start(WikiDir)
2021-02-20 14:03:54 +00:00
shroom.SetHeaderLinks()
2020-08-08 20:10:28 +00:00
go handleGemini()
// See http_admin.go for /admin, /admin/*
initAdmin()
2021-02-24 17:34:42 +00:00
// See http_readers.go for /page/, /hypha/, /text/, /binary/, /attachment/
2021-01-19 18:08:59 +00:00
// See http_mutators.go for /upload-binary/, /upload-text/, /edit/, /delete-ask/, /delete-confirm/, /rename-ask/, /rename-confirm/, /unattach-ask/, /unattach-confirm/
2020-11-14 13:03:06 +00:00
// See http_auth.go for /login, /login-data, /logout, /logout-confirm
// See http_history.go for /history/, /recent-changes
http.HandleFunc("/list", handlerList)
http.HandleFunc("/reindex", handlerReindex)
2021-01-23 19:00:58 +00:00
http.HandleFunc("/update-header-links", handlerUpdateHeaderLinks)
2020-08-31 18:35:36 +00:00
http.HandleFunc("/random", handlerRandom)
http.HandleFunc("/about", handlerAbout)
2021-01-30 18:21:50 +00:00
http.HandleFunc("/user-list", handlerUserList)
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(WikiDir+"/static"))))
http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) {
http.ServeFile(w, rq, WikiDir+"/static/favicon.ico")
})
2020-10-25 18:02:52 +00:00
http.HandleFunc("/static/common.css", handlerStyle)
2020-12-15 18:59:36 +00:00
http.HandleFunc("/static/icon/", handlerIcon)
http.HandleFunc("/robots.txt", handlerRobotsTxt)
http.HandleFunc("/", func(w http.ResponseWriter, rq *http.Request) {
2021-02-17 18:41:35 +00:00
http.Redirect(w, rq, "/hypha/"+util.HomePage, http.StatusSeeOther)
})
2020-10-25 15:06:51 +00:00
log.Fatal(http.ListenAndServe("0.0.0.0:"+util.ServerPort, nil))
2020-06-12 16:22:02 +00:00
}