package main import ( _ "github.com/asdine/storm/v3" _ "go.etcd.io/bbolt" "net/http" "net/url" "path/filepath" "sophuwu.site/myweb/template" "strings" "time" ) type BlogMeta struct { ID string `storm:"unique"` Title string `storm:"index"` Date string `storm:"index"` Desc string `storm:"index"` } type BlogContent struct { ID string `storm:"unique"` Content string `storm:"index"` } func IdGen(title, date string) string { title = strings.ReplaceAll(title, " ", "-") return filepath.Join(date, url.PathEscape(title)) } func SaveBlog(title, desc, body string, date ...string) error { if len(date) == 0 { date = append(date, time.Now().Format("2006-01-02")) } id := IdGen(title, date[0]) err := DB.Save(&BlogContent{ ID: id, Content: body, }) if err != nil { return err } blg := BlogMeta{ ID: id, Title: title, Date: date[0], Desc: desc, } err = DB.Save(&blg) return err } func GetBlog(id string) (meta BlogMeta, content BlogContent, err error) { err = DB.One("ID", id, &content) if err != nil { return } err = DB.One("ID", id, &meta) return } func GetBlogs() ([]BlogMeta, error) { var blogs []BlogMeta // err := DB.All(&blogs) err := DB.AllByIndex("Date", &blogs) if err != nil { return nil, err } for i := 0; i < len(blogs); i++ { for j := i + 1; j < len(blogs); j++ { if blogs[i].Date < blogs[j].Date { blogs[i], blogs[j] = blogs[j], blogs[i] } } } return blogs, err } func BlogHandler(w http.ResponseWriter, r *http.Request) { path := strings.TrimPrefix(r.URL.Path, "/blog/") if path == "" { blogs, err := GetBlogs() if CheckHttpErr(err, w, r, 500) { return } var d template.HTMLDataMap err = DB.Get("pages", "blogs", &d) if CheckHttpErr(err, w, r, 500) { return } d["blogs"] = []BlogMeta(blogs) d.Set("NoBlogs", len(blogs)) err = template.Use(w, r, "blogs", d) CheckHttpErr(err, w, r, 500) return } meta, content, err := GetBlog(path) if CheckHttpErr(err, w, r, 404) { return } data := template.Data(meta.Title, meta.Desc) data.Set("Date", meta.Date) data.SetHTML(content.Content) err = template.Use(w, r, "blog", data) CheckHttpErr(err, w, r, 500) } func BlogManageList(w http.ResponseWriter, r *http.Request) { blogs, err := GetBlogs() if CheckHttpErr(err, w, r, 500) { return } opts := make([]UrlOpt, len(blogs)+1) opts[0] = UrlOpt{Name: "Add new blog", URL: "/manage/blog/?id=new"} for i, b := range blogs { opts[i+1] = UrlOpt{Name: b.Title, URL: "/manage/blog/?id=" + b.ID} } d := template.Data("Manage blogs", "List of blogs") d.Set("Options", opts) err = template.Use(w, r, "manage", d) CheckHttpErr(err, w, r, 500) return } func BlogManager(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/manage/blog/" { HttpErr(w, r, 404) return } if r.Method == "GET" { id := r.URL.Query().Get("id") if id == "" { BlogManageList(w, r) return } if id == "new" { var data = template.Data("New blog", "Create a new blog") data.Set("BlogUrl", "/manage/blog/") data.Set("BlogID", "new") data.Set("BlogDesc", "") data.Set("BlogContent", "") err := template.Use(w, r, "edit", data) CheckHttpErr(err, w, r, 500) return } meta, content, err := GetBlog(id) if CheckHttpErr(err, w, r, 404) { return } data := template.Data("Edit blog "+meta.Title, "Make changes to the content or description") data.Set("BlogUrl", "/manage/blog/") data.Set("BlogID", meta.ID) data.Set("BlogDesc", meta.Desc) data.Set("BlogContent", content.Content) err = template.Use(w, r, "edit", data) CheckHttpErr(err, w, r, 500) return } if r.Method == "POST" { err := r.ParseForm() if CheckHttpErr(err, w, r, 500) { return } id := r.Form.Get("id") title := r.Form.Get("title") desc := r.Form.Get("desc") body := r.Form.Get("content") date := r.Form.Get("date") if id == "" || desc == "" || body == "" || (id == "new" && title == "") { HttpErr(w, r, 400) return } if date == "" { date = time.Now().Format("2006-01-02") } if id == "new" { err = SaveBlog(title, desc, body, date) CheckHttpErr(err, w, r, 500) http.Redirect(w, r, "/manage/blog/", 302) return } meta, content, err := GetBlog(id) if CheckHttpErr(err, w, r, 500) { return } if meta.Desc != desc { meta.Desc = desc err = DB.Update(&meta) if CheckHttpErr(err, w, r, 500) { return } } if content.Content != body { content.Content = body err = DB.Update(&content) if CheckHttpErr(err, w, r, 500) { return } } http.Redirect(w, r, "/manage/blog/", 302) return } }