Initial dirty but working commit
This commit is contained in:
parent
045b274107
commit
28b18ec679
7 changed files with 1927 additions and 0 deletions
recipe
186
recipe/recipe.go
Normal file
186
recipe/recipe.go
Normal file
|
@ -0,0 +1,186 @@
|
|||
package recipe
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/tblyler/goatomic"
|
||||
"github.com/tblyler/recipe-card/doc"
|
||||
)
|
||||
|
||||
// ValidCategoriesOrder defines keys of info in order of importance
|
||||
var ValidCategoriesOrder = []string{
|
||||
"serves",
|
||||
"oven temperature",
|
||||
"ingredients",
|
||||
"preparation",
|
||||
"tips",
|
||||
}
|
||||
|
||||
// validCategories defines keys of Info
|
||||
var validCategories = map[string]bool{
|
||||
"oven temperature": true,
|
||||
"serves": true,
|
||||
"ingredients": true,
|
||||
"preparation": true,
|
||||
"tips": true,
|
||||
}
|
||||
|
||||
// Recipe stores information regarding a specific recipe
|
||||
type Recipe struct {
|
||||
Title string `json:"title"`
|
||||
Info map[string][]string `json:"info"`
|
||||
// FIXME support non-docx
|
||||
DocxPath string `json:"docx_path"`
|
||||
ScanPaths []string `json:"scan_paths"`
|
||||
Image []byte
|
||||
}
|
||||
|
||||
// Summary outputs a nice summary of Info
|
||||
func (r *Recipe) Summary() (output string) {
|
||||
for _, category := range ValidCategoriesOrder {
|
||||
if info, exists := r.Info[category]; exists {
|
||||
if output != "" {
|
||||
// add an extra newline between categories
|
||||
output += "\n"
|
||||
}
|
||||
|
||||
output += category + "\n" + strings.Join(info, "\n")
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ParseFiles for the recipe
|
||||
func (r *Recipe) ParseFiles() error {
|
||||
dir := filepath.Dir(r.DocxPath)
|
||||
|
||||
// get a list of recipe scans
|
||||
infos, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, info := range infos {
|
||||
if info.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
name := strings.ToLower(info.Name())
|
||||
// FIXME support non-jpeg
|
||||
if !strings.HasSuffix(name, ".jpeg") && !strings.HasSuffix(name, ".jpg") {
|
||||
continue
|
||||
}
|
||||
|
||||
r.ScanPaths = append(r.ScanPaths, filepath.Join(dir, info.Name()))
|
||||
}
|
||||
|
||||
sort.Strings(r.ScanPaths)
|
||||
|
||||
file, err := os.Open(r.DocxPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stat, err := file.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
docx, err := doc.NewDocx(file, stat.Size())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Image = docx.Image
|
||||
|
||||
lines, err := docx.Text()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Info = make(map[string][]string)
|
||||
|
||||
titleIsNext := false
|
||||
currentGroup := ""
|
||||
for _, line := range lines {
|
||||
if r.Title == "" {
|
||||
if titleIsNext {
|
||||
r.Title = line
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(strings.ToLower(line), "recipe") {
|
||||
titleIsNext = true
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
lowerLine := strings.ToLower(strings.Replace(line, ":", "", -1))
|
||||
if _, exists := validCategories[lowerLine]; exists {
|
||||
currentGroup = lowerLine
|
||||
continue
|
||||
}
|
||||
|
||||
// make sure a current group is set
|
||||
if currentGroup == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
r.Info[currentGroup] = append(r.Info[currentGroup], line)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RecipesFromPath generates Recipe instances from a path
|
||||
func RecipesFromPath(dirPath string) (recipes []*Recipe, err error) {
|
||||
// get the absolute path of the directory and clean it
|
||||
dirPath, err = filepath.Abs(dirPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
stat, err := os.Stat(dirPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !stat.IsDir() {
|
||||
return nil, fmt.Errorf("Not a directory %s", dirPath)
|
||||
}
|
||||
|
||||
err = filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
|
||||
// skip directories and non-docx files
|
||||
// FIXME support non-docx
|
||||
if info.IsDir() || !strings.HasSuffix(strings.ToLower(path), ".docx") {
|
||||
return nil
|
||||
}
|
||||
|
||||
recipes = append(recipes, &Recipe{
|
||||
DocxPath: path,
|
||||
})
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
wg := goatomic.WorkerGroup{}
|
||||
for _, recipe := range recipes {
|
||||
wg.Add(1)
|
||||
|
||||
go func(recipe *Recipe) {
|
||||
recipe.ParseFiles()
|
||||
wg.Done()
|
||||
}(recipe)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue