func PublishPost(w http.ResponseWriter, r *http.Request) {
	var post Post
	post.Slug = vestigo.Param(r, "slug")
	post, err := post.Get()
	if err != nil {
		log.Println("route PublishPost, post.Get:", err)
		if err.Error() == "not found" {
			render.R.JSON(w, 404, map[string]interface{}{"error": "Not found"})
			return
		}
		render.R.JSON(w, 500, map[string]interface{}{"error": "Internal server error"})
		return
	}
	id, ok := SessionGetValue(r, "id")
	if !ok {
		log.Println("route PublishPost, SessionGetValue:", ok)
		SessionDelete(w, r, "id")
		render.R.HTML(w, 500, "error", "Session could not be fetched. Please log in again.")
		return
	}
	if post.Author != id {
		log.Println("route PublishPost, post.Author and id mismatch")
		render.R.JSON(w, 401, map[string]interface{}{"error": "Unauthorized"})
		return
	}
	var entry Post
	entry = post
	entry.Published = true
	post, err = post.Update(entry)
	if err != nil {
		log.Println("route PublishPost, post.Update:", err)
		if err.Error() == "unauthorized" {
			render.R.JSON(w, 401, map[string]interface{}{"error": "Unauthorized"})
			return
		}
		render.R.JSON(w, 500, map[string]interface{}{"error": "Internal server error"})
		return
	}
	switch Root(r) {
	case "api":
		render.R.JSON(w, 200, map[string]interface{}{"success": "Post published"})
	case "post":
		http.Redirect(w, r, "/post/"+post.Slug, 302)
	}
}
PublishPost is a route which publishes a post and therefore making it appear on frontpage and search.
JSON request returns `HTTP 200 {"success": "Post published"}` on success. Frontend call will redirect to
published page.
Requirender active session cookie.
package routes
import (
	"bufio"
	"errors"
	"log"
	"net/http"
	"strings"
	. "github.com/toldjuuso/vertigo/databases/sqlx"
	"github.com/toldjuuso/vertigo/render"
	. "github.com/toldjuuso/vertigo/session"
	"github.com/gorilla/context"
	"github.com/husobee/vestigo"
	"github.com/toldjuuso/go-jaro-winkler-distance"
)
func GetPost(r *http.Request) (Post, error) {
	rv, ok := context.GetOk(r, "post")
	if !ok {
		return Post{}, errors.New("context not set")
	}
	return rv.(Post), nil
}
func GetSearch(r *http.Request) (Search, error) {
	rv, ok := context.GetOk(r, "search")
	if !ok {
		return Search{}, errors.New("context not set")
	}
	return rv.(Search), nil
}
func Homepage(w http.ResponseWriter, r *http.Request) {
	if Settings.Firstrun {
		render.R.HTML(w, 200, "installation/wizard", nil)
		return
	}
	var post Post
	posts, err := post.GetAll()
	if err != nil {
		log.Println("route Homepage, post.GetAll:", err)
		render.R.JSON(w, 500, map[string]interface{}{"error": "Internal server error"})
		return
	}
	render.R.HTML(w, 200, "home", posts)
}
type Search struct {
	Query string `json:"query" form:"query" binding:"required"`
	Score float64
	Posts []Post
}
func (search Search) Get() (Search, error) {
	var post Post
	posts, err := post.GetAll()
	if err != nil {
		return search, err
	}
	for _, post := range posts {
		if post.Published {
			content := bufio.NewScanner(strings.NewReader(post.Markdown))
			title := bufio.NewScanner(strings.NewReader(post.Title))
			content.Split(bufio.ScanWords)
			title.Split(bufio.ScanWords)
			for content.Scan() {
				if jwd.Calculate(content.Text(), search.Query) >= 0.9 || strings.Contains(search.Query, content.Text()+" ") {
					search.Posts = append(search.Posts, post)
					goto End
				}
			}
			for title.Scan() {
				if jwd.Calculate(title.Text(), search.Query) >= 0.9 || strings.Contains(search.Query, title.Text()+" ") {
					search.Posts = append(search.Posts, post)
					goto End
				}
			}
		}
	End:
	}
	if len(search.Posts) == 0 {
		search.Posts = make([]Post, 0)
	}
	return search, nil
}
func SearchPost(w http.ResponseWriter, r *http.Request) {
	search, err := GetSearch(r)
	if err != nil {
		log.Println("route SearchPost, context GetSearch:", err)
		render.R.JSON(w, 500, map[string]interface{}{"error": "Internal server error"})
		return
	}
	search, err = search.Get()
	if err != nil {
		log.Println("route SearchPost, search.Get:", err)
		render.R.JSON(w, 500, map[string]interface{}{"error": "Internal server error"})
		return
	}
	switch Root(r) {
	case "api":
		render.R.JSON(w, 200, search.Posts)
	case "posts":
		render.R.HTML(w, 200, "search", search.Posts)
	}
}
func CreatePost(w http.ResponseWriter, r *http.Request) {
	post, err := GetPost(r)
	if err != nil {
		log.Println("route CreatePost, context GetPost:", err)
		render.R.JSON(w, 500, map[string]interface{}{"error": "Internal server error"})
		return
	}
	var user User
	id, ok := SessionGetValue(r, "id")
	if !ok {
		log.Println("route CreatePost, SessionGetValue:", ok)
		SessionDelete(w, r, "id")
		render.R.HTML(w, 500, "error", "Session could not be fetched. Please log in again.")
		return
	}
	user.ID = id
	user, err = user.Get()
	if err != nil {
		log.Println("route CreatePost, user.Get:", err)
		SessionDelete(w, r, "id")
		render.R.HTML(w, 500, "error", err)
		return
	}
	post, err = post.Insert(user)
	if err != nil {
		log.Println("route CreatePost, post.Insert:", err)
		render.R.JSON(w, 500, map[string]interface{}{"error": "Internal server error"})
		return
	}
	switch Root(r) {
	case "api":
		render.R.JSON(w, 200, post)
	case "posts":
		http.Redirect(w, r, "/user", 302)
	}
}
func ReadPosts(w http.ResponseWriter, r *http.Request) {
	var post Post
	published := make([]Post, 0)
	posts, err := post.GetAll()
	if err != nil {
		log.Println("route ReadPosts, post.GetAll:", err)
		render.R.JSON(w, 500, map[string]interface{}{"error": "Internal server error"})
		return
	}
	for _, post := range posts {
		if post.Published {
			published = append(published, post)
		}
	}
	render.R.JSON(w, 200, published)
}
func ReadPost(w http.ResponseWriter, r *http.Request) {
	log.Println("url query:", r.URL.Query())
	var post Post
	if vestigo.Param(r, "slug") == "new" {
		render.R.JSON(w, 400, map[string]interface{}{"error": "There can't be a post called 'new'."})
		return
	}
	post.Slug = vestigo.Param(r, "slug")
	post, err := post.Get()
	if err != nil {
		log.Println("route ReadPost, post.Get:", err)
		if err.Error() == "not found" {
			render.R.JSON(w, 404, map[string]interface{}{"error": "Not found"})
			return
		}
		render.R.JSON(w, 500, map[string]interface{}{"error": "Internal server error"})
		return
	}
	go post.Increment()
	switch Root(r) {
	case "api":
		render.R.JSON(w, 200, post)
	case "post":
		render.R.HTML(w, 200, "post/display", post)
	}
}
func EditPost(w http.ResponseWriter, r *http.Request) {
	var post Post
	post.Slug = vestigo.Param(r, "slug")
	post, err := post.Get()
	if err != nil {
		log.Println("route EditPost, post.Get:", err)
		render.R.JSON(w, 500, map[string]interface{}{"error": "Internal server error"})
		return
	}
	render.R.HTML(w, 200, "post/edit", post)
}
func UpdatePost(w http.ResponseWriter, r *http.Request) {
	var post Post
	post.Slug = vestigo.Param(r, "slug")
	post, err := post.Get()
	if err != nil {
		log.Println("route UpdatePost, post.Get:", err)
		if err.Error() == "not found" {
			render.R.JSON(w, 404, map[string]interface{}{"error": "Not found"})
			return
		}
		render.R.JSON(w, 500, map[string]interface{}{"error": "Internal server error"})
		return
	}
	id, ok := SessionGetValue(r, "id")
	if !ok {
		log.Println("route UpdatePost, SessionGetValue:", ok)
		SessionDelete(w, r, "id")
		render.R.HTML(w, 500, "error", "Session could not be fetched. Please log in again.")
		return
	}
	if post.Author != id {
		log.Println("route UpdatePost, post.Author and id mismatch")
		render.R.JSON(w, 401, map[string]interface{}{"error": "Unauthorized"})
		return
	}
	entry, err := GetPost(r)
	if err != nil {
		log.Println("route UpdatePost, context GetPost:", err)
		render.R.JSON(w, 500, map[string]interface{}{"error": "Internal server error"})
		return
	}
	post, err = post.Update(entry)
	if err != nil {
		log.Println("route UpdatePost, post.Update:", err)
		render.R.JSON(w, 500, map[string]interface{}{"error": "Internal server error"})
		return
	}
	switch Root(r) {
	case "api":
		render.R.JSON(w, 200, post)
	case "post":
		http.Redirect(w, r, "/user", 302)
	}
}