Fix media_tags not updating when fingerprint move is detected

reKeyMediaItem was called with item_key values (e.g. "lib1:movie:Inception")
but media_tags stores keys in the shorter UI format (e.g. "lib1:Inception"),
so the UPDATE never matched any rows.

Add itemKeyToMediaKey() to extract the terminal segment of an item_key and
reconstruct the media_key format the UI uses:
  lib1:movie:Inception%20(2010)          → lib1:Inception%20(2010)
  lib1:tv_episode:Show:Season1:ep.mkv   → lib1:ep.mkv
  lib1:mixed_file:dir%2Ffile.mp4        → lib1:dir%2Ffile.mp4

Also skip the UPDATE when old and new media_keys are identical (e.g. a TV
episode moved between seasons keeps the same filename-based media_key).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Garret Patti
2026-04-06 18:59:51 -04:00
parent 38a6886863
commit 58c5e424d9

View File

@@ -531,6 +531,22 @@ function detectMoves(
* Tags on deleted items are intentionally left as orphans — harmless and * Tags on deleted items are intentionally left as orphans — harmless and
* recoverable if the file reappears. * recoverable if the file reappears.
*/ */
/**
* Converts an item_key (used in media_items) to the media_key format used in
* media_tags. The UI constructs media_keys as `${libraryId}:${shortId}` where
* shortId is only the terminal path segment — e.g.:
* "lib1:movie:Inception%20(2010)" → "lib1:Inception%20(2010)"
* "lib1:tv_episode:Show:S1:ep.mkv" → "lib1:ep.mkv"
* "lib1:mixed_file:dir%2Ffile.mp4" → "lib1:dir%2Ffile.mp4"
*/
function itemKeyToMediaKey(itemKey: string): string {
const firstColon = itemKey.indexOf(':')
const lastColon = itemKey.lastIndexOf(':')
const libraryId = itemKey.slice(0, firstColon)
const shortId = itemKey.slice(lastColon + 1)
return `${libraryId}:${shortId}`
}
function reconcileAndPrune( function reconcileAndPrune(
db: Database.Database, db: Database.Database,
libraryId: string, libraryId: string,
@@ -541,7 +557,12 @@ function reconcileAndPrune(
for (const { oldKey, newKey } of moves) { for (const { oldKey, newKey } of moves) {
renameItem.run(newKey, oldKey) renameItem.run(newKey, oldKey)
reKeyMediaItem(oldKey, newKey) // Convert item_keys to the media_key format actually used in media_tags
const oldMediaKey = itemKeyToMediaKey(oldKey)
const newMediaKey = itemKeyToMediaKey(newKey)
if (oldMediaKey !== newMediaKey) {
reKeyMediaItem(oldMediaKey, newMediaKey)
}
console.log(`[scanner] fingerprint match: renamed "${oldKey}" → "${newKey}"`) console.log(`[scanner] fingerprint match: renamed "${oldKey}" → "${newKey}"`)
} }