2026-02-19 10:21:27 +00:00
|
|
|
package models
|
|
|
|
|
|
2026-02-20 23:22:10 +00:00
|
|
|
import (
|
|
|
|
|
"bufio"
|
|
|
|
|
"fmt"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
"unicode"
|
|
|
|
|
)
|
2026-02-19 10:21:27 +00:00
|
|
|
|
|
|
|
|
type Post struct {
|
|
|
|
|
ID int64
|
|
|
|
|
SiteID int64
|
|
|
|
|
GUID string
|
|
|
|
|
Title string
|
|
|
|
|
Body string
|
|
|
|
|
Slug string
|
|
|
|
|
CreatedAt time.Time
|
|
|
|
|
PublishedAt time.Time
|
|
|
|
|
}
|
2026-02-20 23:22:10 +00:00
|
|
|
|
|
|
|
|
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 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, " ")
|
|
|
|
|
}
|