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 }