hugo-micropub/entry.go

141 lines
4.0 KiB
Go
Raw Normal View History

2019-11-07 10:00:24 +00:00
package main
import (
"errors"
"fmt"
"math/rand"
"net/url"
"strings"
"time"
)
type Entry struct {
Content string
Name string
Categories []string
Slug string
Summary string
InReplyTo string
LikeOf string
RepostOf string
section string
location string
filename string
token string
}
func CreateEntry(contentType ContentType, body string) (*Entry, error) {
if contentType == WwwForm {
bodyValues, err := url.ParseQuery(body)
if err != nil {
return nil, errors.New("failed to parse query")
}
return createEntryFromURLValues(bodyValues)
} else if contentType == Json || contentType == Multipart {
return nil, errors.New("multipart and json content-type are not implemented yet")
} else {
return nil, errors.New("unsupported content-type")
}
}
func createEntryFromURLValues(bodyValues url.Values) (*Entry, error) {
if h, ok := bodyValues["h"]; ok && len(h) == 1 && h[0] != "entry" {
return nil, errors.New("only entry type is supported so far")
}
if _, ok := bodyValues["content"]; ok {
entry := new(Entry)
entry.Content = bodyValues["content"][0]
if name, ok := bodyValues["name"]; ok {
entry.Name = name[0]
}
if category, ok := bodyValues["category"]; ok {
entry.Categories = category
} else if categories, ok := bodyValues["category[]"]; ok {
entry.Categories = categories
} else {
entry.Categories = nil
}
if slug, ok := bodyValues["mp-slug"]; ok && len(slug) > 0 && slug[0] != "" {
entry.Slug = slug[0]
}
if summary, ok := bodyValues["summary"]; ok {
entry.Summary = summary[0]
}
if inReplyTo, ok := bodyValues["in-reply-to"]; ok {
entry.InReplyTo = inReplyTo[0]
}
if likeOf, ok := bodyValues["like-of"]; ok {
entry.LikeOf = likeOf[0]
}
if repostOf, ok := bodyValues["repost-of"]; ok {
entry.RepostOf = repostOf[0]
}
if token, ok := bodyValues["access_token"]; ok {
entry.token = "Bearer " + token[0]
}
err := computeExtraSettings(entry)
if err != nil {
return nil, err
}
return entry, nil
}
return nil, errors.New("error parsing the entry from URL Values")
}
func computeExtraSettings(entry *Entry) error {
now := time.Now()
entry.section = "micro"
// Find settings hidden in category strings
filteredCategories := make([]string, 0)
for _, category := range entry.Categories {
if strings.HasPrefix(category, "section-") {
entry.section = strings.TrimPrefix(category, "section-")
} else if strings.HasPrefix(category, "slug-") {
entry.Slug = strings.TrimPrefix(category, "slug-")
} else {
filteredCategories = append(filteredCategories, category)
}
}
entry.Categories = filteredCategories
// Compute slug if empty
if len(entry.Slug) == 0 || entry.Slug == "" {
random := generateRandomString(now, 5)
entry.Slug = fmt.Sprintf("%v-%02d-%02d-%v", now.Year(), int(now.Month()), now.Day(), random)
}
// Compute filename and location
blogURL, err := GetBlogURL()
if err != nil {
return err
}
if entry.section == "posts" {
entry.filename = "content/" + entry.section + "/" + entry.Slug + ".md"
entry.location = blogURL + entry.section + "/" + entry.Slug
} else if entry.section == "thoughts" || entry.section == "links" {
entry.filename = fmt.Sprintf("content/%v/%02d/%02d/%v.md", entry.section, now.Year(), int(now.Month()), entry.Slug)
entry.location = fmt.Sprintf("%v%v/%02d/%02d/%v", blogURL, entry.section, now.Year(), int(now.Month()), entry.Slug)
} else {
entry.filename = "content/" + entry.section + "/" + entry.Slug + ".md"
entry.location = blogURL + entry.section + "/" + entry.Slug
}
return nil
}
func generateRandomString(now time.Time, n int) string {
rand.Seed(now.UnixNano())
letters := []rune("abcdefghijklmnopqrstuvwxyz")
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}
func WriteEntry(entry *Entry) (string, error) {
file := WriteHugoPost(entry)
err := CommitEntry(entry.filename, file, entry.Name)
if err != nil {
return "", err
}
return entry.location, nil
}