From 830741cd65dbaa3ebed5b22c1905de33d312cdae Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Fri, 14 Aug 2026 08:26:32 -0400 Subject: [PATCH] feat(sidecar): key book map by per-format hashes The sidecar config's books map is keyed by the primary SHA-256 (UUID fallback). A device holding a converted format (KEPUB/PDF) whose hash lives only in media_item_formats could not resolve its file through the sidecar. After inserting the primary-keyed entry, also register the same entry under each per-format hash from media_item_formats (first write wins, so a primary hash is never shadowed). Devices now resolve converted files via the sidecar the same way the server's BookResolver does. Applied to both the GET and download sidecar builders. --- internal/handlers/sidecar.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/internal/handlers/sidecar.go b/internal/handlers/sidecar.go index 3bd0f77..449c2d0 100644 --- a/internal/handlers/sidecar.go +++ b/internal/handlers/sidecar.go @@ -134,6 +134,21 @@ func (h *SidecarHandler) GetSidecarConfig(c *echo.Context) error { SHA256: item.FileSha256.String, FilePath: item.FilePath, } + + // Also key the book by each per-format hash (KEPUB/PDF/...), so a device + // holding a converted format resolves via the sidecar the same way it + // would via BookResolver on the server. + formats, ferr := h.db.GetMediaItemFormats(ctx, item.ID) + if ferr == nil { + entry := books[key] + for _, f := range formats { + if f.FileSha256.Valid && f.FileSha256.String != "" { + if _, exists := books[f.FileSha256.String]; !exists { + books[f.FileSha256.String] = entry + } + } + } + } } // Get collections @@ -269,6 +284,21 @@ func (h *SidecarHandler) DownloadSidecarConfig(c *echo.Context) error { SHA256: item.FileSha256.String, FilePath: item.FilePath, } + + // Also key the book by each per-format hash (KEPUB/PDF/...), so a device + // holding a converted format resolves via the sidecar the same way it + // would via BookResolver on the server. + formats, ferr := h.db.GetMediaItemFormats(ctx, item.ID) + if ferr == nil { + entry := books[key] + for _, f := range formats { + if f.FileSha256.Valid && f.FileSha256.String != "" { + if _, exists := books[f.FileSha256.String]; !exists { + books[f.FileSha256.String] = entry + } + } + } + } } // Get collections