Files
opds-proxy/convert/mobi.go
Evan Buss ccc6217014 feat: structured logging improvements
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
2024-08-10 20:03:34 +00:00

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
}