sophuwu.site > myweb   
              206
            
             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
	}
}