forked from Ivasoft/opds-proxy
This change adds a child logger with request information to the http request context. Also improved the log format for clarity. - Unescaped the query string - Use JSON log format when not in dev mode. - Added request ip to the request child logger. - The child logger is passed to the converter so we can associate any errors with a specific request / file. - Add book file name as a logger attribute - Add user agent header as a logger attribute - Log the "X-Forwarded-For" header, falling back to RemoteAddr
70 lines
1.5 KiB
Go
70 lines
1.5 KiB
Go
package convert
|
|
|
|
import (
|
|
"bytes"
|
|
"log/slog"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
type MobiConverter struct {
|
|
mutex sync.Mutex
|
|
available bool
|
|
availableOnce sync.Once
|
|
}
|
|
|
|
func (mc *MobiConverter) Available() bool {
|
|
mc.availableOnce.Do(func() {
|
|
path, err := exec.LookPath("kindlegen")
|
|
mc.available = err == nil && path != ""
|
|
})
|
|
return mc.available
|
|
}
|
|
|
|
func (mc *MobiConverter) Convert(log *slog.Logger, input string) (string, error) {
|
|
mc.mutex.Lock()
|
|
defer mc.mutex.Unlock()
|
|
|
|
// KindleGen doesn't allow the input file to be in a different directory
|
|
// So set the working directory to the input file.
|
|
outDir, _ := filepath.Abs(filepath.Dir(input))
|
|
mobiFile := filepath.Join(outDir, strings.Replace(filepath.Base(input), ".epub", ".mobi", 1))
|
|
|
|
// And remove the directory from file paths
|
|
cmd := exec.Command("kindlegen",
|
|
filepath.Base(input),
|
|
"-dont_append_source", "-c1", "-o",
|
|
filepath.Base(mobiFile),
|
|
)
|
|
cmd.Dir = outDir
|
|
|
|
var out bytes.Buffer
|
|
var stderr bytes.Buffer
|
|
cmd.Stdout = &out
|
|
cmd.Stderr = &stderr
|
|
err := cmd.Run()
|
|
if err != nil {
|
|
isError := true
|
|
if exiterr, ok := err.(*exec.ExitError); ok {
|
|
// Sometimes warnings cause a 1 exit-code, but the file is still created
|
|
log.Info("Exit code", slog.Any("code", exiterr.ExitCode()))
|
|
if exiterr.ExitCode() == 1 {
|
|
isError = false
|
|
}
|
|
}
|
|
|
|
if isError {
|
|
log.Error("Error converting file",
|
|
slog.Any("error", err),
|
|
slog.String("stdout", out.String()),
|
|
slog.String("stderr", stderr.String()),
|
|
)
|
|
return "", err
|
|
}
|
|
}
|
|
|
|
return mobiFile, nil
|
|
}
|