build now should be compatible with python's accorder...

This commit is contained in:
educative 2021-11-18 00:32:37 +01:00
parent 926d42fbcc
commit 3629b3dc49
4 changed files with 80 additions and 55 deletions

View File

@ -2,10 +2,14 @@ package cmd
import ( import (
"fmt" "fmt"
"os"
"accorder/pkg/calibre"
// "accorder/pkg/calibre"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/satori/go.uuid"
) )
var buildCmd = &cobra.Command{ var buildCmd = &cobra.Command{
@ -21,14 +25,24 @@ the configuration file for the future use (therefore: 'accorder build PROFILE'
should be enough for the next successful build).`, should be enough for the next successful build).`,
Args: OnlyProfileArgument, Args: OnlyProfileArgument,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
fromFlag := viper.GetString("directory") calibrePath := viper.GetString(fmt.Sprintf("%s.calibre_path", args[0]))
fromConfig := viper.GetString(fmt.Sprintf("%s.directory", args[0])) librarianName := viper.GetString(fmt.Sprintf("%s.librarian_name", args[0]))
if fromFlag != "" && fromFlag != fromConfig { libraryUUID := viper.GetString(fmt.Sprintf("%s.library_uuid", args[0]))
fmt.Printf("Would you like to write the new directory path:\n%s\ninto the configuration file?\n", viper.GetString("directory")) librarySecret := viper.GetString(fmt.Sprintf("%s.library_secret", args[0]))
fromConfig = fromFlag
calibrePathFromCli, _ := cmd.PersistentFlags().GetString("directory")
librarianNameFromCli, _ := cmd.PersistentFlags().GetString("librarian")
if calibrePathFromCli != "" || librarianNameFromCli != "" || libraryUUID == "" || librarySecret == "" {
if libraryUUID == "" {
libraryUUID = uuid.NewV4().String()
viper.Set(fmt.Sprintf("%s.library_uuid", args[0]), libraryUUID)
} else if librarySecret == "" {
librarySecret = uuid.NewV4().String()
viper.Set(fmt.Sprintf("%s.library_secret", args[0]), librarySecret)
}
viper.WriteConfig()
} }
fmt.Println("DIRECTORY:", fromConfig) calibre.RenderStandaloneApp(calibrePath, librarianName, libraryUUID, librarySecret)
// calibre.RenderStandaloneApp()
}, },
} }
@ -38,6 +52,8 @@ func init() {
buildCmd.PersistentFlags().StringP("jsonpath", "j", "", "Path where to render all metadata into JSON.") buildCmd.PersistentFlags().StringP("jsonpath", "j", "", "Path where to render all metadata into JSON.")
buildCmd.PersistentFlags().StringP("bibtex", "b", "", "Import books from BibTex file into Calibre.") buildCmd.PersistentFlags().StringP("bibtex", "b", "", "Import books from BibTex file into Calibre.")
CustomHelpOutput(buildCmd) CustomHelpOutput(buildCmd)
viper.BindPFlag("directory", buildCmd.PersistentFlags().Lookup("directory")) profile := os.Args[len(os.Args)-1]
viper.BindPFlag(fmt.Sprintf("%s.calibre_path", profile), buildCmd.PersistentFlags().Lookup("directory"))
viper.BindPFlag(fmt.Sprintf("%s.librarian_name", profile), buildCmd.PersistentFlags().Lookup("librarian"))
rootCmd.AddCommand(buildCmd) rootCmd.AddCommand(buildCmd)
} }

6
go.mod
View File

@ -3,11 +3,9 @@ module accorder
go 1.16 go 1.16
require ( require (
github.com/cespare/xxhash v1.1.0 // indirect github.com/karrick/godirwalk v1.16.1
github.com/karrick/godirwalk v1.16.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-homedir v1.1.0
github.com/satori/go.uuid v1.2.0
github.com/spf13/cobra v1.2.1 github.com/spf13/cobra v1.2.1
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.9.0 github.com/spf13/viper v1.9.0
nullprogram.com/x/uuid v1.2.1 // indirect
) )

7
go.sum
View File

@ -54,7 +54,6 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
@ -252,6 +251,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@ -688,10 +689,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
nullprogram.com/x/isaac64 v1.0.0 h1:60wAUcmF8LI7bqmIR84aCviOFYsZ16uzVVQwEv0KMo0=
nullprogram.com/x/isaac64 v1.0.0/go.mod h1:50jMhq3WThwRpM4z6xTHwp94BMqha3WbuKWb2vRxr78=
nullprogram.com/x/uuid v1.2.1 h1:dBg/lObcs+vykLutnXWbZp++/mRvyCnZcsq+BRfoJY4=
nullprogram.com/x/uuid v1.2.1/go.mod h1:NmzZbQYLdE9DEeN3zar52XwVIehpxzbXHxsbV/08T2I=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@ -1,7 +1,10 @@
package calibre package calibre
import ( import (
"crypto/hmac"
"crypto/md5"
"embed" "embed"
"encoding/hex"
"encoding/json" "encoding/json"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
@ -15,10 +18,9 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/cespare/xxhash" // "github.com/cespare/xxhash"
// "github.com/google/uuid"
"github.com/karrick/godirwalk" "github.com/karrick/godirwalk"
"nullprogram.com/x/uuid" "github.com/satori/go.uuid"
) )
var ( var (
@ -26,9 +28,9 @@ var (
embResources embed.FS embResources embed.FS
) )
func c(err error) { func c(err error, m string) {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err, m)
} }
} }
@ -179,28 +181,49 @@ func (book BookOpf) Identifiers() []*IdentifierJSON {
return identifiers return identifiers
} }
// Uuid returns calibre's book uuid...
func (book BookOpf) Uuid(librarySecret string) string {
for _, i := range book.Metadata.Identifiers {
if i.Id == "uuid_id" {
h := hmac.New(md5.New, []byte(librarySecret))
h.Write([]byte(i.Value))
sha := hex.EncodeToString(h.Sum(nil))
u, err := uuid.FromString(sha)
if err != nil {
fmt.Println(err)
}
return u.String()
}
}
return ""
}
// Formats return list of files and info on them // Formats return list of files and info on them
func Formats(path string) []*FormatJSON { func Formats(path string) []*FormatJSON {
if strings.HasSuffix(path, "/") != true {
path = path + "/"
}
formats := []*FormatJSON{} formats := []*FormatJSON{}
files, err := os.ReadDir(path) files, err := os.ReadDir(path)
c(err) c(err, "list of formats...")
for _, f := range files { for _, f := range files {
if f.Name() != "metadata.opf" && f.Name() != "cover.jpg" { if f.Name() != "metadata.opf" && f.Name() != "cover.jpg" {
fi, err := f.Info() fi, err := f.Info()
c(err) c(err, "file info in Formats")
x, err := os.Open(filepath.Join(path, f.Name())) x, err := os.Open(filepath.Join(path, f.Name()))
c(err) c(err, "open file in Formats")
defer x.Close() defer x.Close()
xxHash := xxhash.New() // xxHash := xxhash.New()
_, err = io.Copy(xxHash, x) // _, err = io.Copy(xxHash, x)
c(err) // c(err, "io.Copy xxHash in Formats")
formats = append(formats, &FormatJSON{ formats = append(formats, &FormatJSON{
Format: strings.ReplaceAll(filepath.Ext(f.Name()), ".", ""), Format: strings.ReplaceAll(filepath.Ext(f.Name()), ".", ""),
DirPath: path, DirPath: path,
FileName: f.Name(), FileName: f.Name(),
Size: fi.Size(), Size: fi.Size(),
XXHash: xxHash.Sum64(), // XXHash: xxHash.Sum64(),
}) })
} }
} }
@ -209,7 +232,7 @@ func Formats(path string) []*FormatJSON {
func lsEmbResources() { func lsEmbResources() {
_ = fs.WalkDir(embResources, ".", func(path string, d fs.DirEntry, err error) error { _ = fs.WalkDir(embResources, ".", func(path string, d fs.DirEntry, err error) error {
c(err) c(err, "")
// fmt.Println(" ", path) // fmt.Println(" ", path)
_ = path _ = path
return nil return nil
@ -219,21 +242,19 @@ func lsEmbResources() {
func copyEmbResources(destPath string) { func copyEmbResources(destPath string) {
_ = fs.WalkDir(embResources, ".", func(fsPath string, fsEntry fs.DirEntry, err error) error { _ = fs.WalkDir(embResources, ".", func(fsPath string, fsEntry fs.DirEntry, err error) error {
destFsPath := strings.ReplaceAll(fsPath, "embResources/", "") destFsPath := strings.ReplaceAll(fsPath, "embResources/", "")
c(err) if fsPath == "." || fsPath == "embResources" {
if fsPath == "." {
return nil return nil
} else if fsEntry.IsDir() { } else if fsEntry.IsDir() {
err := os.MkdirAll(filepath.Join(destPath, destFsPath), 0755) err := os.MkdirAll(filepath.Join(destPath, destFsPath), 0755)
c(err) c(err, "make new directory at the destination...")
} else { } else {
newFile, err := os.Create(destFsPath) newFile, err := os.Create(filepath.Join(destPath, destFsPath))
c(err) c(err, "create new file at the destination..")
defer newFile.Close() defer newFile.Close()
embFile, err := embResources.Open(fsPath) embFile, err := embResources.Open(fsPath)
c(err)
_, err = io.Copy(newFile, embFile) _, err = io.Copy(newFile, embFile)
c(err) c(err, "copy embResources/ file into the new file at the destination...")
} }
return nil return nil
}) })
@ -242,7 +263,7 @@ func copyEmbResources(destPath string) {
func writeDataJs(calibrePath string, books []*BookJSON) { func writeDataJs(calibrePath string, books []*BookJSON) {
// j, _ := json.MarshalIndent(&BooksJSON{books}) // j, _ := json.MarshalIndent(&BooksJSON{books})
dataJsFirst, err := os.Create(filepath.Join(calibrePath, "static", "data1.js")) dataJsFirst, err := os.Create(filepath.Join(calibrePath, "static", "data1.js"))
c(err) c(err, "create dataJsFirst file...")
defer dataJsFirst.Close() defer dataJsFirst.Close()
j1, _ := json.Marshal(&DataJs{ j1, _ := json.Marshal(&DataJs{
@ -270,7 +291,7 @@ func writeDataJs(calibrePath string, books []*BookJSON) {
} }
dataJs, err := os.Create(filepath.Join(calibrePath, "static", fmt.Sprintf("data%d.js", counter))) dataJs, err := os.Create(filepath.Join(calibrePath, "static", fmt.Sprintf("data%d.js", counter)))
c(err) c(err, "create dataJs file...")
defer dataJs.Close() defer dataJs.Close()
if endBlock <= len(books) { if endBlock <= len(books) {
@ -296,14 +317,7 @@ func PrintExePath() {
fmt.Println(os.Executable()) fmt.Println(os.Executable())
} }
func RenderStandaloneApp(calibrePath string) { func RenderStandaloneApp(calibrePath, librarianName, libraryUUID, librarySecret string) {
// exePath, err := os.Executable()
// c(err)
// calibrePath := fmt.Sprintf("%s/", filepath.Dir(exePath))
// calibrePath := "/home/m/CalibreLibraries/MarcellMarsBooks/"
// calibrePath := "/media/m/My Book/motw/motw_calibre_libraries/MarcellMarsBooks/"
fmt.Println(calibrePath)
var outputs sync.Map var outputs sync.Map
var wg sync.WaitGroup var wg sync.WaitGroup
count := 0 count := 0
@ -315,18 +329,18 @@ func RenderStandaloneApp(calibrePath string) {
wg.Add(1) wg.Add(1)
go func(bookOpf *BookOpf) { go func(bookOpf *BookOpf) {
// randSuffix := uuid.New() // randSuffix := uuid.New()
randSuffix := uuid.NewGen() // randSuffix := uuid.NewV4()
relativeDirPath := strings.NewReplacer(calibrePath, "", "metadata.opf", "").Replace(path) relativeDirPath := strings.NewReplacer(calibrePath, "", "metadata.opf", "").Replace(path)
f, _ := os.ReadFile(path) f, _ := os.ReadFile(path)
_ = xml.Unmarshal([]byte(f), &bookOpf) _ = xml.Unmarshal([]byte(f), &bookOpf)
book := &BookJSON{ book := &BookJSON{
// Id: randSuffix.String(), // Id: randSuffix.String(),
Id: randSuffix.NewV4().String(), Id: bookOpf.Uuid(librarySecret),
Title: bookOpf.Metadata.Title, Title: bookOpf.Metadata.Title,
Librarian: "Aaron Elbakyan", Librarian: librarianName,
// LibraryUUID: randSuffix.String(), // LibraryUUID: randSuffix.String(),
LibraryUUID: randSuffix.NewV4().String(), LibraryUUID: libraryUUID,
TitleSort: bookOpf.TitleSort(), TitleSort: bookOpf.TitleSort(),
Authors: bookOpf.Authors(), Authors: bookOpf.Authors(),
Pubdate: bookOpf.Metadata.Published, Pubdate: bookOpf.Metadata.Published,
@ -337,10 +351,10 @@ func RenderStandaloneApp(calibrePath string) {
Languages: bookOpf.Languages(), Languages: bookOpf.Languages(),
Identifiers: bookOpf.Identifiers(), Identifiers: bookOpf.Identifiers(),
Formats: Formats(filepath.Join(calibrePath, relativeDirPath)), Formats: Formats(filepath.Join(calibrePath, relativeDirPath)),
CoverUrl: filepath.Join(relativeDirPath, "cover.jpg"), CoverUrl: filepath.Join(relativeDirPath[1:], "cover.jpg"),
} }
// outputs.Store(fmt.Sprintf("%s_%s", book.LastModified, randSuffix.String()), book) // outputs.Store(fmt.Sprintf("%s_%s", book.LastModified, randSuffix.String()), book)
outputs.Store(fmt.Sprintf("%s_%s", book.LastModified, randSuffix.NewV4().String()), book) outputs.Store(fmt.Sprintf("%s_%s", book.LastModified, uuid.NewV4().String()), book)
wg.Done() wg.Done()
}(bookOpf) }(bookOpf)
} }
@ -357,7 +371,7 @@ func RenderStandaloneApp(calibrePath string) {
Unsorted: true}) Unsorted: true})
wg.Wait() wg.Wait()
c(err) c(err, "")
var keysByDate []string var keysByDate []string
outputs.Range(func(k, v interface{}) bool { outputs.Range(func(k, v interface{}) bool {