117 lines
2.0 KiB
Go
117 lines
2.0 KiB
Go
package tal
|
|
|
|
import (
|
|
"bufio"
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
var metaRegex = regexp.MustCompile(`^#([a-zA-Z]+) (.*)$`)
|
|
|
|
type Repo struct {
|
|
URL string
|
|
Path string
|
|
Update bool
|
|
Books []Book
|
|
}
|
|
|
|
func (lr *Repo) GetMeta() map[string]map[string][]Book {
|
|
meta := map[string]map[string][]Book{}
|
|
for _, book := range lr.Books {
|
|
for key, value := range book.Meta {
|
|
if meta[key] == nil {
|
|
meta[key] = map[string][]Book{}
|
|
}
|
|
meta[key][value] = append(meta[key][value], book)
|
|
}
|
|
}
|
|
return meta
|
|
}
|
|
|
|
func (lr *Repo) Scan() error {
|
|
books := lr.scanTree(lr.Path, 1, 3, ".muse")
|
|
|
|
if len(books) == 0 {
|
|
return errors.New(fmt.Sprintf("No library found at %s", lr.Path))
|
|
}
|
|
|
|
for _, p := range books {
|
|
meta, err := readMeta(p)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
lr.Books = append(lr.Books, Book{
|
|
Path: p,
|
|
Base: strings.TrimSuffix(path.Base(p), ".muse"),
|
|
Meta: meta,
|
|
})
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (lr *Repo) scanTree(p string, dirlen uint8, max uint8, suffix string) []string {
|
|
var paths []string
|
|
|
|
files, err := ioutil.ReadDir(p)
|
|
if err != nil {
|
|
return paths
|
|
}
|
|
|
|
for _, entry := range files {
|
|
name := entry.Name()
|
|
subdir := filepath.Join(p, name)
|
|
|
|
if dirlen == max {
|
|
if strings.HasSuffix(name, suffix) {
|
|
paths = append(paths, subdir)
|
|
}
|
|
} else {
|
|
if !entry.IsDir() || len(name) != int(dirlen) {
|
|
continue
|
|
}
|
|
paths = append(paths, lr.scanTree(subdir, dirlen+1, max, suffix)...)
|
|
}
|
|
}
|
|
|
|
return paths
|
|
}
|
|
|
|
func readMeta(p string) (map[string]string, error) {
|
|
meta := map[string]string{}
|
|
|
|
f, err := os.Open(p)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scanner := bufio.NewScanner(f)
|
|
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
|
|
if len(line) > 0 && line[0] == '#' {
|
|
result := metaRegex.FindStringSubmatch(line)
|
|
|
|
if len(result) > 0 {
|
|
tag := strings.TrimSpace(result[1])
|
|
value := strings.TrimSpace(result[2])
|
|
meta[tag] = value
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
|
|
f.Close()
|
|
|
|
return meta, nil
|
|
}
|