weiro/models/posts.go

104 lines
2.2 KiB
Go

package models
import (
"bufio"
"fmt"
"strings"
"time"
"unicode"
)
const (
StatePublished = iota
StateDraft
)
type Post struct {
ID int64 `json:"id"`
SiteID int64 `json:"site_id"`
State int `json:"state"`
GUID string `json:"guid"`
Title string `json:"title"`
Body string `json:"body"`
Slug string `json:"slug"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
DeletedAt time.Time `json:"deleted_at,omitempty"`
PublishedAt time.Time `json:"published_at,omitempty"`
}
func (p *Post) NanoSummary() string {
if p.Title != "" {
return p.Title
}
firstWords := firstNWords(p.Body, 7, wordForSummary)
if firstWords == "" {
firstWords = "(no content)"
} else if len(firstWords) < len(p.Body) {
return firstWords + "..."
}
return firstWords
}
func (p *Post) BestSlug() string {
if p.Slug != "" {
return p.Slug
}
bestDateToUse := p.PublishedAt
if bestDateToUse.IsZero() {
bestDateToUse = p.CreatedAt
}
slugPath := firstNWords(p.Title, 3, wordForSlug)
if slugPath == "" {
slugPath = firstNWords(p.Body, 3, wordForSlug)
}
if slugPath != "" {
slugPath = strings.Replace(strings.ToLower(slugPath), " ", "-", -1)
} else {
slugPath = p.GUID
if slugPath == "" {
slugPath = bestDateToUse.Format("150405")
}
}
datePart := fmt.Sprintf("%04d/%02d/%02d", bestDateToUse.Year(), bestDateToUse.Month(), bestDateToUse.Day())
return fmt.Sprintf("/%s/%s", datePart, slugPath)
}
func wordForSummary(word string) string {
return word
}
func wordForSlug(word string) string {
var sb strings.Builder
for _, c := range word {
if unicode.IsLetter(c) || unicode.IsNumber(c) {
sb.WriteRune(c)
}
}
return sb.String()
}
func firstNWords(s string, n int, keepWord func(word string) string) string {
if n == 0 {
return ""
}
suitableWords := make([]string, 0, n)
scnr := bufio.NewScanner(strings.NewReader(s))
scnr.Split(bufio.ScanWords)
for scnr.Scan() {
word := scnr.Text()
if w := keepWord(word); w != "" {
suitableWords = append(suitableWords, w)
if len(suitableWords) >= n {
break
}
}
}
return strings.Join(suitableWords, " ")
}