muse/storage/entrylist.go

176 lines
3.4 KiB
Go

package storage
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"sort"
"sync"
"time"
"github.com/gorilla/feeds"
)
type (
EntryList struct {
Filename string
ModTime time.Time
v []*Entry
mu sync.RWMutex
}
)
func (list *EntryList) Len() int { return len(list.v) }
func (list *EntryList) Swap(i, j int) { list.v[i], list.v[j] = list.v[j], list.v[i] }
func (list *EntryList) Less(i, j int) bool {
return time.Time(list.v[i].Date).After(time.Time(list.v[j].Date))
}
func (list *EntryList) modified() (mod bool) {
info, err := os.Stat(list.Filename)
if err == nil {
mod = list.ModTime.Before(info.ModTime())
list.ModTime = info.ModTime()
} else {
mod = true
}
return
}
func (list *EntryList) write() (err error) {
data, err := json.MarshalIndent(list.v, "", " ")
if err == nil {
err = ioutil.WriteFile(list.Filename, data, 0644)
}
if err == nil {
list.ModTime = time.Now()
}
return
}
func (list *EntryList) read() (err error) {
if list.modified() {
list.v = make([]*Entry, 0, len(list.v))
if data, err := ioutil.ReadFile(list.Filename); err == nil {
err = json.Unmarshal(data, &list.v)
}
}
return
}
func (list *EntryList) GetEntries() (entry []*Entry, err error) {
list.mu.RLock()
defer list.mu.RUnlock()
err = list.read()
entry = list.v
return
}
func (list *EntryList) AddEntry(entry *Entry) (err error) {
list.mu.Lock()
defer list.mu.Unlock()
if err = list.read(); err == nil {
list.v = append(list.v, entry)
sort.Sort(list)
err = list.write()
}
return
}
func (list *EntryList) ReadSliceList(oval int, nval int) (entries []*Entry, err error) {
list.mu.RLock()
defer list.mu.RUnlock()
if nval <= 0 {
nval = list.Len()
}
if oval <= 0 {
oval = 0
}
err = list.read()
if err == nil {
if oval >= list.Len() {
entries = nil
} else if oval+nval >= list.Len() {
entries = list.v[oval:]
} else {
entries = list.v[oval : oval+nval]
}
}
return
}
func (list *EntryList) DeleteElement(pos int) (err error) {
list.mu.Lock()
defer list.mu.Unlock()
if err = list.read(); err == nil {
if pos >= 0 && pos < list.Len() {
if pos == 0 {
list.v = list.v[pos+1:]
} else if pos == list.Len()-1 {
list.v = list.v[:pos]
} else {
list.v = append(list.v[:pos], list.v[pos+1:]...)
}
err = list.write()
}
}
return
}
// TODO rutas relativas
func (list *EntryList) GetFeed() (feed *feeds.Feed) {
list.mu.RLock()
defer list.mu.RUnlock()
err := list.read()
if err == nil {
feed = &feeds.Feed{
Title: "danoloan.es muse",
Link: &feeds.Link{Href: "https://danoloan.es/muse"},
Description: "bitácora musical de danoloan",
Author: &feeds.Author{Name: "danoloan", Email: "danolo@danoloan.es"},
}
feed.Items = make([]*feeds.Item, 0, list.Len())
for _, elem := range list.v {
item := &feeds.Item{
Created: time.Time(elem.Date),
}
if elem.Track != "" {
item.Title = elem.Track
} else if elem.Album != "" {
item.Title = elem.Album
}
item.Description = fmt.Sprintf("<p>%s - %s</p>\n", item.Title, elem.Artist)
if elem.Cover != "" {
item.Description = fmt.Sprintf("%s<img src=\"%s\"/>\n", item.Description, elem.Cover)
}
if elem.Linkto != "" {
item.Link = &feeds.Link{Href: elem.Linkto}
} else {
item.Link = &feeds.Link{Href: "https://danoloan.es/muse"}
}
feed.Items = append(feed.Items, item)
}
}
return
}