refactor: remove dead code across server, templ pages, and client modules
Deadcode-verified removals (RTA reachability from main, cross-checked with -test and textual xrefs): Go server: - whole files: middleware/transaction.go, middleware/error_handler.go, middleware/password_validator.go (live registration machinery kept), handlers/sync.go, sync/offline.go - unrouted endpoints: auth UpdateUsername/UpdateEmail, timezone settings handler, OPDS RegisterOPDS, Kobo LibrarySync handler, ReaderHandler.ShowReader, JSON-data twins on collections/library - duplicate book-matching handlers (book_matching.go Handler twins, matching.go MatchingHandler twins), superseded helpers (router.parseUUID, handlers.ValidateDeviceToken, normalizePath, userExists, generateLockID) Templ/client: - never-routed pages: api_explorer.templ, queue.templ and their client modules api-explorer.ts, api-explorer-docs.ts, queue.ts - fully orphaned wrapper modules events.ts, dom.ts - broken clearSyncQueue (called a nonexistent endpoint) and the hidden, never-populated sync-queue section on the devices page - 166+ unused exports demoted to private (knip-verified); ~85 truly dead declarations removed via tsc noUnusedLocals fixpoint - stale 'interactive API Explorer' claims dropped from docs The docs drift-gate package (internal/docs), templ-bound modules (dashboard, stats, header, index, login, profile*, bookshelf, collections, toast-error), sqlc-generated code, and web/static are intentionally untouched.
This commit is contained in:
1 parent
8733e83f1f
commit
8631aa00bf
107 files changed
+689
-3443
No files matched your search
@@ -343,197 +343,3 @@ func (mh *MatchingHandler) GetBookMatches(c *echo.Context) error {
|
||||
|
||||
return c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// BulkLinkBooks handles POST /api/sync/bulk-link-books
|
||||
func (mh *MatchingHandler) BulkLinkBooks(c *echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
|
||||
var req BulkLinkBooksRequest
|
||||
if err := c.Bind(&req); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{
|
||||
"error": "Invalid request body",
|
||||
})
|
||||
}
|
||||
|
||||
results := make([]map[string]interface{}, 0, len(req.Links))
|
||||
|
||||
for _, link := range req.Links {
|
||||
unlinkedBook, err := mh.db.GetUnlinkedBookByID(ctx, pgtype.UUID{Bytes: link.UnlinkedBookID, Valid: true})
|
||||
if err != nil {
|
||||
results = append(results, map[string]interface{}{
|
||||
"unlinked_book_id": link.UnlinkedBookID.String(),
|
||||
"status": "error",
|
||||
"error": "Unlinked book not found",
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = mh.db.CreateDeviceFileAlias(ctx, database.CreateDeviceFileAliasParams{
|
||||
MediaItemID: pgtype.UUID{Bytes: link.MediaItemID, Valid: true},
|
||||
DeviceID: unlinkedBook.DeviceID,
|
||||
FilePath: unlinkedBook.FilePath.String,
|
||||
FileSha256: pgtype.Text{String: "", Valid: false},
|
||||
ConfidenceScore: toFloat8(link.ConfidenceScore),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
results = append(results, map[string]interface{}{
|
||||
"unlinked_book_id": link.UnlinkedBookID.String(),
|
||||
"status": "error",
|
||||
"error": err.Error(),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = mh.db.LinkUnlinkedBook(ctx, database.LinkUnlinkedBookParams{
|
||||
ID: pgtype.UUID{Bytes: link.UnlinkedBookID, Valid: true},
|
||||
MediaItemID: pgtype.UUID{Bytes: link.MediaItemID, Valid: true},
|
||||
ConfidenceScore: toFloat8(link.ConfidenceScore),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
results = append(results, map[string]interface{}{
|
||||
"unlinked_book_id": link.UnlinkedBookID.String(),
|
||||
"status": "warning",
|
||||
"error": "Linked but failed to mark as resolved",
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
results = append(results, map[string]interface{}{
|
||||
"unlinked_book_id": link.UnlinkedBookID.String(),
|
||||
"status": "success",
|
||||
"media_item_id": link.MediaItemID.String(),
|
||||
})
|
||||
}
|
||||
|
||||
successfulCount := 0
|
||||
for _, r := range results {
|
||||
if r["status"] == "success" {
|
||||
successfulCount++
|
||||
}
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"results": results,
|
||||
"total": len(req.Links),
|
||||
"successful": successfulCount,
|
||||
"failed": len(req.Links) - successfulCount,
|
||||
})
|
||||
}
|
||||
|
||||
// AutoLinkBooks handles POST /api/sync/auto-link-books
|
||||
func (mh *MatchingHandler) AutoLinkBooks(c *echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
matchingService := mh.getMatchingService()
|
||||
|
||||
var req AutoLinkBooksRequest
|
||||
if err := c.Bind(&req); err != nil {
|
||||
req.ConfidenceThreshold = 0.8
|
||||
req.Limit = 50
|
||||
}
|
||||
|
||||
if req.ConfidenceThreshold == 0 {
|
||||
req.ConfidenceThreshold = 0.8
|
||||
}
|
||||
if req.Limit == 0 {
|
||||
req.Limit = 50
|
||||
}
|
||||
|
||||
offset := 0
|
||||
unlinked, err := mh.db.ListUnresolvedUnlinkedBooks(ctx, database.ListUnresolvedUnlinkedBooksParams{
|
||||
Limit: int32(req.Limit),
|
||||
Offset: int32(offset),
|
||||
})
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||
"error": "Failed to get unlinked books",
|
||||
})
|
||||
}
|
||||
|
||||
results := make([]map[string]interface{}, 0)
|
||||
|
||||
for _, book := range unlinked {
|
||||
queryReq := &services.BookQueryRequest{
|
||||
Title: book.Title.String,
|
||||
}
|
||||
|
||||
match, err := matchingService.QueryBooks(ctx, queryReq)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(match.Matches) > 0 && match.Matches[0].Confidence >= req.ConfidenceThreshold {
|
||||
bestMatch := match.Matches[0]
|
||||
|
||||
_, err := mh.db.CreateDeviceFileAlias(ctx, database.CreateDeviceFileAliasParams{
|
||||
MediaItemID: pgtype.UUID{Bytes: bestMatch.BookhoardUUID, Valid: true},
|
||||
DeviceID: book.DeviceID,
|
||||
FilePath: book.FilePath.String,
|
||||
FileSha256: pgtype.Text{String: "", Valid: false},
|
||||
ConfidenceScore: toFloat8(bestMatch.Confidence),
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
mh.db.LinkUnlinkedBook(ctx, database.LinkUnlinkedBookParams{
|
||||
ID: book.ID,
|
||||
MediaItemID: pgtype.UUID{Bytes: bestMatch.BookhoardUUID, Valid: true},
|
||||
ConfidenceScore: toFloat8(bestMatch.Confidence),
|
||||
})
|
||||
|
||||
results = append(results, map[string]interface{}{
|
||||
"unlinked_book_id": uuid.UUID(book.ID.Bytes).String(),
|
||||
"title": book.Title.String,
|
||||
"matched_media_item_id": bestMatch.BookhoardUUID.String(),
|
||||
"confidence": bestMatch.Confidence,
|
||||
"match_method": bestMatch.MatchMethod,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"auto_linked": len(results),
|
||||
"results": results,
|
||||
})
|
||||
}
|
||||
|
||||
// GetUnlinkedBookSuggestions handles GET /api/sync/unlinked-books/:id/suggestions
|
||||
func (mh *MatchingHandler) GetUnlinkedBookSuggestions(c *echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
matchingService := mh.getMatchingService()
|
||||
|
||||
unlinkedBookID := c.Param("id")
|
||||
unlinkedUUID, err := uuid.Parse(unlinkedBookID)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{
|
||||
"error": "Invalid unlinked book ID",
|
||||
})
|
||||
}
|
||||
|
||||
unlinked, err := mh.db.GetUnlinkedBookByID(ctx, pgtype.UUID{Bytes: unlinkedUUID, Valid: true})
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusNotFound, map[string]string{
|
||||
"error": "Unlinked book not found",
|
||||
})
|
||||
}
|
||||
|
||||
matches, err := matchingService.QueryBooks(ctx, &services.BookQueryRequest{
|
||||
Title: unlinked.Title.String,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||
"error": "Failed to query matches",
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"unlinked_book_id": unlinkedBookID,
|
||||
"title_from_device": unlinked.Title.String,
|
||||
"sha256": "",
|
||||
"suggestions": matches.Matches,
|
||||
"total_suggestions": len(matches.Matches),
|
||||
"action": matches.Action,
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user