You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
2.6 KiB
127 lines
2.6 KiB
package main |
|
|
|
import ( |
|
"bytes" |
|
"encoding/json" |
|
"flag" |
|
"html/template" |
|
"io/ioutil" |
|
"log" |
|
"net/http" |
|
"os" |
|
"os/exec" |
|
"path" |
|
"strconv" |
|
"strings" |
|
|
|
"github.com/russross/blackfriday" |
|
) |
|
|
|
func main() { |
|
loadConfig() |
|
|
|
_ = os.Setenv(`GIT_TERMINAL_PROMPT`, `0`) |
|
|
|
if err := updateTemplate(); err != nil { |
|
log.Fatal(`Failed to load template. (` + err.Error() + `)`) |
|
} |
|
|
|
log.Fatal(http.ListenAndServe("127.0.0.1:"+strconv.Itoa(config.Port), http.HandlerFunc(serveRequest))) |
|
} |
|
|
|
var config struct { |
|
Port int |
|
Template string |
|
Pages string |
|
Static string |
|
Webhook string |
|
} |
|
|
|
func loadConfig() { |
|
flag.IntVar(&config.Port, `port`, 80, `The port mdsite will listen on`) |
|
flag.StringVar(&config.Template, `template`, `template.html`, `The template used by mdsite`) |
|
flag.StringVar(&config.Pages, `pages`, `pages`, `The OS path used when searching a page`) |
|
flag.StringVar(&config.Static, `static`, `static`, `The OS path used for static resource`) |
|
flag.StringVar(&config.Webhook, `webhook`, ``, `The secret for webhooks to update the content`) |
|
flag.Parse() |
|
} |
|
|
|
var t *template.Template |
|
|
|
func updateTemplate() error { |
|
tmpl, err := template.ParseFiles(config.Template) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
t = tmpl |
|
return nil |
|
} |
|
|
|
func serveRequest(w http.ResponseWriter, r *http.Request) { |
|
if r.Method == http.MethodPost && config.Webhook != `` && r.URL.Path == `/hook` { |
|
var input struct { |
|
Secret string `json:"secret"` |
|
} |
|
err := json.NewDecoder(r.Body).Decode(&input) |
|
_ = r.Body.Close() |
|
if err != nil || input.Secret != config.Webhook { |
|
w.WriteHeader(403) |
|
return |
|
} |
|
|
|
err = exec.Command(`git`, `fetch`).Run() |
|
if err == nil { |
|
err = exec.Command(`git`, `reset`, `--hard`, `origin/master`).Run() |
|
} |
|
if err == nil { |
|
err = updateTemplate() |
|
} |
|
|
|
if err != nil { |
|
w.WriteHeader(500) |
|
w.Write([]byte(`Update failed`)) |
|
} |
|
return |
|
} |
|
|
|
if strings.HasPrefix(r.URL.Path, `/static/`) { |
|
path := path.Join(config.Static, path.Clean(strings.TrimPrefix(r.URL.Path, `/static/`))) |
|
http.ServeFile(w, r, path) |
|
return |
|
} |
|
servePage(w, r) |
|
} |
|
|
|
func servePage(w http.ResponseWriter, r *http.Request) { |
|
p := path.Join(config.Pages, path.Clean(r.URL.Path)) |
|
|
|
s, err := os.Stat(p) |
|
if err == nil && s.IsDir() { |
|
if p[len(p)-1] != '/' { |
|
p += `/` |
|
} |
|
p += `index` |
|
} |
|
|
|
c, err := ioutil.ReadFile(p + `.md`) |
|
if err != nil { |
|
w.WriteHeader(404) |
|
return |
|
} |
|
|
|
var title string |
|
if idx := bytes.IndexByte(c, '\n'); idx != -1 { |
|
fl := string(c[:idx]) |
|
if strings.HasPrefix(fl, `[title]:`) { |
|
title = strings.TrimPrefix(fl, `[title]:`) |
|
} |
|
} |
|
|
|
data := struct { |
|
Title string |
|
Content template.HTML |
|
}{title, template.HTML(blackfriday.MarkdownCommon(c))} |
|
|
|
t.Execute(w, data) |
|
}
|
|
|