This commit is contained in:
+36
-1
@@ -320,4 +320,39 @@ def register_routes(
|
||||
}
|
||||
except Exception as e:
|
||||
_log("ERROR", f"Optimized scan failed: {e}")
|
||||
raise HTTPException(status_code=500, detail=f"Optimized scan failed: {str(e)}")
|
||||
raise HTTPException(status_code=500, detail=f"Optimized scan failed: {str(e)}")
|
||||
|
||||
@app.post("/nfo/strip-lockdata")
|
||||
async def strip_lockdata_from_library(background_tasks: BackgroundTasks):
|
||||
"""Strip lockdata elements from all NFO files for Emby compatibility"""
|
||||
try:
|
||||
_log("INFO", "Lockdata stripping initiated via API")
|
||||
|
||||
def strip_lockdata_task():
|
||||
total_processed = 0
|
||||
|
||||
# Process TV libraries
|
||||
for tv_path in config.tv_paths:
|
||||
if tv_path.exists():
|
||||
_log("INFO", f"Stripping lockdata from TV library: {tv_path}")
|
||||
processed = tv_processor.nfo_manager.strip_lockdata_from_directory(tv_path)
|
||||
total_processed += processed
|
||||
|
||||
# Process Movie libraries
|
||||
for movie_path in config.movie_paths:
|
||||
if movie_path.exists():
|
||||
_log("INFO", f"Stripping lockdata from movie library: {movie_path}")
|
||||
processed = movie_processor.nfo_manager.strip_lockdata_from_directory(movie_path)
|
||||
total_processed += processed
|
||||
|
||||
_log("INFO", f"Lockdata stripping complete: {total_processed} NFO files processed")
|
||||
|
||||
background_tasks.add_task(strip_lockdata_task)
|
||||
return {
|
||||
"status": "started",
|
||||
"message": "Lockdata stripping initiated for Emby compatibility",
|
||||
"note": "This will remove <lockdata>true</lockdata> from all NFO files"
|
||||
}
|
||||
except Exception as e:
|
||||
_log("ERROR", f"Lockdata stripping failed: {e}")
|
||||
raise HTTPException(status_code=500, detail=f"Lockdata stripping failed: {str(e)}")
|
||||
+97
-26
@@ -138,11 +138,26 @@ class NFOManager:
|
||||
# Look for NFOGuard fields
|
||||
dateadded_elem = root.find('.//dateadded')
|
||||
premiered_elem = root.find('.//premiered')
|
||||
lockdata_elem = root.find('.//lockdata')
|
||||
# Strip any existing lockdata elements for Emby compatibility
|
||||
lockdata_elements = root.findall('.//lockdata')
|
||||
if lockdata_elements:
|
||||
modified = False
|
||||
for lockdata_elem in lockdata_elements:
|
||||
# Find parent and remove the element
|
||||
for parent in root.iter():
|
||||
if lockdata_elem in parent:
|
||||
parent.remove(lockdata_elem)
|
||||
modified = True
|
||||
_log("DEBUG", f"Stripped lockdata element from {nfo_path.name}")
|
||||
break
|
||||
if modified:
|
||||
# Write back the cleaned NFO
|
||||
tree = ET.ElementTree(root)
|
||||
ET.indent(tree, space=" ", level=0)
|
||||
tree.write(nfo_path, encoding="utf-8", xml_declaration=True)
|
||||
|
||||
# Only consider it NFOGuard-managed if it has dateadded and lockdata
|
||||
if (dateadded_elem is not None and dateadded_elem.text and
|
||||
lockdata_elem is not None and lockdata_elem.text == "true"):
|
||||
# Only consider it NFOGuard-managed if it has dateadded (lockdata no longer required)
|
||||
if (dateadded_elem is not None and dateadded_elem.text):
|
||||
|
||||
result = {
|
||||
"dateadded": dateadded_elem.text.strip(),
|
||||
@@ -176,11 +191,26 @@ class NFOManager:
|
||||
# Look for NFOGuard fields in episode NFO
|
||||
dateadded_elem = root.find('.//dateadded')
|
||||
aired_elem = root.find('.//aired')
|
||||
lockdata_elem = root.find('.//lockdata')
|
||||
# Strip any existing lockdata elements for Emby compatibility
|
||||
lockdata_elements = root.findall('.//lockdata')
|
||||
if lockdata_elements:
|
||||
modified = False
|
||||
for lockdata_elem in lockdata_elements:
|
||||
# Find parent and remove the element
|
||||
for parent in root.iter():
|
||||
if lockdata_elem in parent:
|
||||
parent.remove(lockdata_elem)
|
||||
modified = True
|
||||
_log("DEBUG", f"Stripped lockdata element from {nfo_path.name}")
|
||||
break
|
||||
if modified:
|
||||
# Write back the cleaned NFO
|
||||
tree = ET.ElementTree(root)
|
||||
ET.indent(tree, space=" ", level=0)
|
||||
tree.write(nfo_path, encoding="utf-8", xml_declaration=True)
|
||||
|
||||
# Only consider it NFOGuard-managed if it has dateadded and lockdata
|
||||
if (dateadded_elem is not None and dateadded_elem.text and
|
||||
lockdata_elem is not None and lockdata_elem.text == "true"):
|
||||
# Only consider it NFOGuard-managed if it has dateadded (lockdata no longer required)
|
||||
if (dateadded_elem is not None and dateadded_elem.text):
|
||||
|
||||
result = {
|
||||
"dateadded": dateadded_elem.text.strip(),
|
||||
@@ -350,7 +380,7 @@ class NFOManager:
|
||||
|
||||
# Remove existing NFOGuard-managed elements to avoid duplicates
|
||||
# These will be re-added at the very bottom
|
||||
nfoguard_fields = ["dateadded", "lockdata", "premiered", "year"]
|
||||
nfoguard_fields = ["dateadded", "premiered", "year"]
|
||||
for tag in nfoguard_fields:
|
||||
existing = movie.find(tag)
|
||||
if existing is not None:
|
||||
@@ -410,11 +440,7 @@ class NFOManager:
|
||||
movie.append(dateadded_elem)
|
||||
print(f"✅ Added dateadded to NFO: {dateadded}")
|
||||
|
||||
# Add lockdata at the very end
|
||||
if lock_metadata:
|
||||
lockdata = ET.Element("lockdata")
|
||||
lockdata.text = "true"
|
||||
movie.append(lockdata)
|
||||
# Note: lockdata element removed for Emby compatibility
|
||||
|
||||
# Write file with proper formatting
|
||||
tree = ET.ElementTree(movie)
|
||||
@@ -476,9 +502,7 @@ class NFOManager:
|
||||
tvdb_uniqueid = ET.SubElement(tvshow, "uniqueid", type="tvdb")
|
||||
tvdb_uniqueid.text = tvdb_id
|
||||
|
||||
# Add lockdata at the very end
|
||||
lockdata = ET.SubElement(tvshow, "lockdata")
|
||||
lockdata.text = "true"
|
||||
# Note: lockdata element removed for Emby compatibility
|
||||
|
||||
# Add NFOGuard comment at the beginning
|
||||
comment_text = f" Created by {self.manager_brand} "
|
||||
@@ -521,7 +545,7 @@ class NFOManager:
|
||||
raise ValueError("Root element is not <season>")
|
||||
|
||||
# Remove existing NFOGuard-managed elements
|
||||
for tag in ["seasonnumber", "lockdata"]:
|
||||
for tag in ["seasonnumber"]:
|
||||
existing = season.find(tag)
|
||||
if existing is not None:
|
||||
season.remove(existing)
|
||||
@@ -538,9 +562,7 @@ class NFOManager:
|
||||
seasonnumber = ET.SubElement(season, "seasonnumber")
|
||||
seasonnumber.text = str(season_number)
|
||||
|
||||
# Add lockdata at the end
|
||||
lockdata = ET.SubElement(season, "lockdata")
|
||||
lockdata.text = "true"
|
||||
# Note: lockdata element removed for Emby compatibility
|
||||
|
||||
# Add NFOGuard comment at the beginning
|
||||
comment_text = f" Created by {self.manager_brand} "
|
||||
@@ -653,7 +675,7 @@ class NFOManager:
|
||||
preserved_values = {}
|
||||
|
||||
# Extract and preserve NFOGuard-managed fields (we'll re-add these at the bottom)
|
||||
nfoguard_fields = ["aired", "dateadded", "lockdata", "season", "episode"]
|
||||
nfoguard_fields = ["aired", "dateadded", "season", "episode"]
|
||||
for tag in nfoguard_fields:
|
||||
existing = episode.find(tag)
|
||||
if existing is not None:
|
||||
@@ -737,10 +759,7 @@ class NFOManager:
|
||||
dateadded_elem = ET.SubElement(episode, "dateadded")
|
||||
dateadded_elem.text = dateadded
|
||||
|
||||
# Add lockdata at the very end
|
||||
if lock_metadata:
|
||||
lockdata = ET.SubElement(episode, "lockdata")
|
||||
lockdata.text = "true"
|
||||
# Note: lockdata element removed for Emby compatibility
|
||||
|
||||
# Add NFOGuard comment at the bottom with other NFOGuard fields
|
||||
nfoguard_comment = ET.Comment(f" Created by {self.manager_brand} - Source: {source} ")
|
||||
@@ -803,4 +822,56 @@ class NFOManager:
|
||||
print(f"✅ Updated {len(updated_files)} video file timestamps in {movie_dir.name}")
|
||||
else:
|
||||
print(f"⚠️ No video files found to update in {movie_dir.name}")
|
||||
|
||||
def strip_lockdata_from_nfo(self, nfo_path: Path) -> bool:
|
||||
"""Strip existing lockdata elements from NFO file for Emby compatibility"""
|
||||
if not nfo_path.exists():
|
||||
return False
|
||||
|
||||
try:
|
||||
tree = ET.parse(nfo_path)
|
||||
root = tree.getroot()
|
||||
|
||||
# Find and remove all lockdata elements
|
||||
lockdata_elements = root.findall('.//lockdata')
|
||||
if not lockdata_elements:
|
||||
return False # No lockdata found, nothing to remove
|
||||
|
||||
removed_count = 0
|
||||
for lockdata_elem in lockdata_elements:
|
||||
# Find parent and remove the element
|
||||
for parent in root.iter():
|
||||
if lockdata_elem in parent:
|
||||
parent.remove(lockdata_elem)
|
||||
removed_count += 1
|
||||
break
|
||||
|
||||
if removed_count > 0:
|
||||
# Write back the modified NFO
|
||||
ET.indent(tree, space=" ", level=0)
|
||||
tree.write(nfo_path, encoding="utf-8", xml_declaration=True)
|
||||
_log("INFO", f"Removed {removed_count} lockdata elements from {nfo_path.name}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
_log("ERROR", f"Error stripping lockdata from {nfo_path}: {e}")
|
||||
|
||||
return False
|
||||
|
||||
def strip_lockdata_from_directory(self, directory_path: Path) -> int:
|
||||
"""Strip lockdata from all NFO files in a directory"""
|
||||
if not directory_path.exists():
|
||||
return 0
|
||||
|
||||
processed_count = 0
|
||||
nfo_files = list(directory_path.glob("**/*.nfo"))
|
||||
|
||||
_log("INFO", f"Scanning {len(nfo_files)} NFO files for lockdata removal in {directory_path}")
|
||||
|
||||
for nfo_file in nfo_files:
|
||||
if self.strip_lockdata_from_nfo(nfo_file):
|
||||
processed_count += 1
|
||||
|
||||
_log("INFO", f"Stripped lockdata from {processed_count} NFO files in {directory_path}")
|
||||
return processed_count
|
||||
|
||||
|
||||
Reference in New Issue
Block a user