2017-11-24 19:56:32 +00:00
|
|
|
package posts
|
|
|
|
|
2017-12-23 02:34:58 +00:00
|
|
|
import (
|
|
|
|
"sort"
|
|
|
|
)
|
2017-11-24 19:56:32 +00:00
|
|
|
|
|
|
|
// UpdateIndex updates a post's metadata in the blog index.
|
|
|
|
func UpdateIndex(p *Post) error {
|
|
|
|
idx, err := GetIndex()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return idx.Update(p)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Index caches high level metadata about the blog's contents for fast access.
|
|
|
|
type Index struct {
|
2019-06-05 23:18:38 +00:00
|
|
|
Posts map[int]Post `json:"posts"`
|
|
|
|
Fragments map[string]int `json:"fragments"`
|
|
|
|
Thumbnails map[int]string `json:"thumbnails"`
|
2017-11-24 19:56:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetIndex loads the index, or rebuilds it first if it doesn't exist.
|
|
|
|
func GetIndex() (*Index, error) {
|
|
|
|
if !DB.Exists("blog/index") {
|
|
|
|
index, err := RebuildIndex()
|
|
|
|
return index, err
|
|
|
|
}
|
|
|
|
idx := &Index{}
|
|
|
|
err := DB.Get("blog/index", &idx)
|
|
|
|
return idx, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// RebuildIndex builds the index from scratch.
|
|
|
|
func RebuildIndex() (*Index, error) {
|
|
|
|
idx := &Index{
|
2019-06-05 23:18:38 +00:00
|
|
|
Posts: map[int]Post{},
|
|
|
|
Fragments: map[string]int{},
|
|
|
|
Thumbnails: map[int]string{},
|
2017-11-24 19:56:32 +00:00
|
|
|
}
|
|
|
|
entries, _ := DB.List("blog/posts")
|
|
|
|
for _, doc := range entries {
|
|
|
|
p := &Post{}
|
|
|
|
err := DB.Get(doc, &p)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
idx.Update(p)
|
|
|
|
}
|
|
|
|
|
|
|
|
return idx, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update a blog's entry in the index.
|
|
|
|
func (idx *Index) Update(p *Post) error {
|
|
|
|
idx.Posts[p.ID] = Post{
|
2019-03-15 21:12:38 +00:00
|
|
|
ID: p.ID,
|
|
|
|
Title: p.Title,
|
|
|
|
Fragment: p.Fragment,
|
|
|
|
AuthorID: p.AuthorID,
|
|
|
|
Privacy: p.Privacy,
|
|
|
|
Sticky: p.Sticky,
|
|
|
|
EnableComments: p.EnableComments,
|
|
|
|
Tags: p.Tags,
|
|
|
|
Created: p.Created,
|
|
|
|
Updated: p.Updated,
|
2017-11-24 19:56:32 +00:00
|
|
|
}
|
2018-04-14 05:08:44 +00:00
|
|
|
idx.Fragments[p.Fragment] = p.ID
|
2019-06-05 23:18:38 +00:00
|
|
|
|
|
|
|
// Find a thumbnail image if possible.
|
|
|
|
if thumb, ok := p.ExtractThumbnail(); ok {
|
|
|
|
idx.Thumbnails[p.ID] = thumb
|
|
|
|
}
|
|
|
|
|
2017-11-24 19:56:32 +00:00
|
|
|
err := DB.Commit("blog/index", idx)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete a blog's entry from the index.
|
|
|
|
func (idx *Index) Delete(p *Post) error {
|
|
|
|
delete(idx.Posts, p.ID)
|
2018-04-29 19:56:37 +00:00
|
|
|
delete(idx.Fragments, p.Fragment)
|
2017-11-24 19:56:32 +00:00
|
|
|
return DB.Commit("blog/index", idx)
|
|
|
|
}
|
|
|
|
|
2017-12-23 02:34:58 +00:00
|
|
|
// Tag is a response from Tags including metadata about it.
|
|
|
|
type Tag struct {
|
|
|
|
Name string
|
|
|
|
Count int
|
|
|
|
}
|
|
|
|
|
2018-04-14 05:08:44 +00:00
|
|
|
// ByPopularity sort type.
|
2017-12-23 02:34:58 +00:00
|
|
|
type ByPopularity []Tag
|
|
|
|
|
|
|
|
func (s ByPopularity) Len() int {
|
|
|
|
return len(s)
|
|
|
|
}
|
|
|
|
func (s ByPopularity) Swap(i, j int) {
|
|
|
|
s[i], s[j] = s[j], s[i]
|
|
|
|
}
|
|
|
|
func (s ByPopularity) Less(i, j int) bool {
|
|
|
|
if s[i].Count < s[j].Count {
|
|
|
|
return true
|
|
|
|
} else if s[i].Count > s[j].Count {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return s[i].Name < s[j].Name
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tags returns the tags sorted by most frequent.
|
|
|
|
func (idx *Index) Tags() ([]Tag, error) {
|
|
|
|
idx, err := GetIndex()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
unique := map[string]*Tag{}
|
|
|
|
|
|
|
|
for _, post := range idx.Posts {
|
|
|
|
for _, name := range post.Tags {
|
|
|
|
tag, ok := unique[name]
|
|
|
|
if !ok {
|
|
|
|
tag = &Tag{name, 0}
|
|
|
|
unique[name] = tag
|
|
|
|
}
|
|
|
|
tag.Count++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort the tags.
|
|
|
|
tags := []Tag{}
|
|
|
|
for _, tag := range unique {
|
|
|
|
tags = append(tags, *tag)
|
|
|
|
}
|
|
|
|
sort.Sort(sort.Reverse(ByPopularity(tags)))
|
|
|
|
|
|
|
|
return tags, nil
|
|
|
|
}
|