104 lines
2.2 KiB
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, " ")
|
|
}
|