refrag code for RenameFile plugin

This commit is contained in:
David Maisonave
2024-08-27 19:24:28 -04:00
parent 7063168536
commit aba11888ce
15 changed files with 848 additions and 430 deletions

View File

@@ -2,30 +2,17 @@
# By David Maisonave (aka Axter) Jul-2024 (https://www.axter.com/)
# Get the latest developers version from following link: https://github.com/David-Maisonave/Axter-Stash/tree/main/plugins/RenameFile
# Based on source code from https://github.com/Serechops/Serechops-Stash/tree/main/plugins/Renamer
import os
import sys
import shutil
import hashlib
import json
import os, sys, shutil, json, requests, hashlib, pathlib, logging
from pathlib import Path
import requests
import logging
from logging.handlers import RotatingFileHandler
import stashapi.log as log # Importing stashapi.log as log for critical events ONLY
from stashapi.stashapp import StashInterface
from StashPluginHelper import StashPluginHelper
from renamefile_settings import config # Import settings from renamefile_settings.py
# **********************************************************************
# Constant global variables --------------------------------------------
LOG_FILE_PATH = f"{Path(__file__).resolve().parent}\\{Path(__file__).stem}.log"
FORMAT = "[%(asctime)s - LN:%(lineno)s] %(message)s"
DEFAULT_FIELD_KEY_LIST = "title,performers,studio,tags" # Default Field Key List with the desired order
PLUGIN_ID = Path(__file__).stem.lower()
DEFAULT_SEPERATOR = "-"
PLUGIN_ARGS = False
PLUGIN_ARGS_MODE = False
WRAPPER_STYLES = config["wrapper_styles"]
POSTFIX_STYLES = config["postfix_styles"]
# GraphQL query to fetch all scenes
QUERY_ALL_SCENES = """
query AllScenes {
@@ -35,133 +22,81 @@ QUERY_ALL_SCENES = """
}
}
"""
RFH = RotatingFileHandler(
filename=LOG_FILE_PATH,
mode='a',
maxBytes=8*1024*1024, # Configure logging for this script with max log file size of 2000K
backupCount=2,
encoding=None,
delay=0
)
# **********************************************************************
# Global variables --------------------------------------------
inputToUpdateScenePost = False
exitMsg = "Change success!!"
# Configure local log file for plugin within plugin folder having a limited max log file size
logging.basicConfig(level=logging.INFO, format=FORMAT, datefmt="%y%m%d %H:%M:%S", handlers=[RFH])
logger = logging.getLogger(PLUGIN_ID)
# **********************************************************************
# ----------------------------------------------------------------------
# Code section to fetch variables from Plugin UI and from renamefile_settings.py
json_input = json.loads(sys.stdin.read())
FRAGMENT_SERVER = json_input['server_connection']
stash = StashInterface(FRAGMENT_SERVER)
pluginConfiguration = stash.get_configuration()["plugins"]
settings = {
"performerAppend": False,
"studioAppend": False,
"tagAppend": False,
"z_keyFIeldsIncludeInFileName": False,
"zafileRenameViaRaname": False,
"zafileRenameViaMove": False,
"zfieldKeyList": DEFAULT_FIELD_KEY_LIST,
"zmaximumTagKeys": 12,
"zseparators": DEFAULT_SEPERATOR,
"zzdebugTracing": False,
"zzdryRun": False,
}
if PLUGIN_ID in pluginConfiguration:
settings.update(pluginConfiguration[PLUGIN_ID])
stash = StashPluginHelper(
settings=settings,
config=config,
maxbytes=10*1024*1024,
)
stash.Status(logLevel=logging.DEBUG)
if stash.PLUGIN_ID in stash.PLUGIN_CONFIGURATION:
stash.pluginSettings.update(stash.PLUGIN_CONFIGURATION[stash.PLUGIN_ID])
# ----------------------------------------------------------------------
debugTracing = settings["zzdebugTracing"]
WRAPPER_STYLES = config["wrapper_styles"]
POSTFIX_STYLES = config["postfix_styles"]
# Extract dry_run setting from settings
dry_run = settings["zzdryRun"]
dry_run = stash.pluginSettings["zzdryRun"]
dry_run_prefix = ''
try:
PLUGIN_ARGS = json_input['args']
PLUGIN_ARGS_MODE = json_input['args']["mode"]
if stash.JSON_INPUT['args']['hookContext']['input']: inputToUpdateScenePost = True # This avoids calling rename logic twice
except:
pass
try:
if json_input['args']['hookContext']['input']: inputToUpdateScenePost = True # This avoids calling rename logic twice
except:
pass
logger.info(f"\nStarting (debugTracing={debugTracing}) (dry_run={dry_run}) (PLUGIN_ARGS_MODE={PLUGIN_ARGS_MODE}) (inputToUpdateScenePost={inputToUpdateScenePost})************************************************")
if debugTracing: logger.info("settings: %s " % (settings,))
if PLUGIN_ID in pluginConfiguration:
if debugTracing: logger.info(f"Debug Tracing (pluginConfiguration[PLUGIN_ID]={pluginConfiguration[PLUGIN_ID]})................")
# if 'zmaximumTagKeys' not in pluginConfiguration[PLUGIN_ID]:
# if debugTracing: logger.info("Debug Tracing................")
# try:
# stash.configure_plugin(PLUGIN_ID, settings)
# stash.configure_plugin("renamefile", {"zmaximumTagKeys": 12})
# except Exception as e:
# logger.error(f"configure_plugin failed!!! Error: {e}")
# logger.exception('Got exception on main handler')
# pass
# # stash.configure_plugin(PLUGIN_ID, settings) # , init_defaults=True
# if debugTracing: logger.info("Debug Tracing................")
stash.Trace("settings: %s " % (stash.pluginSettings,))
if dry_run:
logger.info("Dry run mode is enabled.")
stash.Log("Dry run mode is enabled.")
dry_run_prefix = "Would've "
if debugTracing: logger.info("Debug Tracing................")
max_tag_keys = settings["zmaximumTagKeys"] if settings["zmaximumTagKeys"] != 0 else 12 # Need this incase use explicitly sets value to zero in UI
if debugTracing: logger.info("Debug Tracing................")
max_tag_keys = stash.pluginSettings["zmaximumTagKeys"] if stash.pluginSettings["zmaximumTagKeys"] != 0 else 12 # Need this incase use explicitly sets value to zero in UI
# ToDo: Add split logic here to slpit possible string array into an array
exclude_paths = config["pathToExclude"]
exclude_paths = exclude_paths.split()
if debugTracing: logger.info(f"Debug Tracing (exclude_paths={exclude_paths})................")
stash.Trace(f"(exclude_paths={exclude_paths})")
excluded_tags = config["excludeTags"]
# Extract tag whitelist from settings
tag_whitelist = config["tagWhitelist"]
if debugTracing: logger.info("Debug Tracing................")
if not tag_whitelist:
tag_whitelist = ""
if debugTracing: logger.info(f"Debug Tracing (tag_whitelist={tag_whitelist})................")
stash.Trace(f"(tag_whitelist={tag_whitelist})")
endpointHost = json_input['server_connection']['Host']
endpointHost = stash.JSON_INPUT['server_connection']['Host']
if endpointHost == "0.0.0.0":
endpointHost = "localhost"
endpoint = f"{json_input['server_connection']['Scheme']}://{endpointHost}:{json_input['server_connection']['Port']}/graphql"
endpoint = f"{stash.JSON_INPUT['server_connection']['Scheme']}://{endpointHost}:{stash.JSON_INPUT['server_connection']['Port']}/graphql"
if debugTracing: logger.info(f"Debug Tracing (endpoint={endpoint})................")
# Extract rename_files and move_files settings from renamefile_settings.py
rename_files = config["rename_files"]
move_files = False if settings["zafileRenameViaRaname"] else True
if debugTracing: logger.info("Debug Tracing................")
fieldKeyList = settings["zfieldKeyList"] # Default Field Key List with the desired order
stash.Trace(f"(endpoint={endpoint})")
move_files = stash.pluginSettings["zafileRenameViaMove"]
fieldKeyList = stash.pluginSettings["zfieldKeyList"] # Default Field Key List with the desired order
if not fieldKeyList or fieldKeyList == "":
fieldKeyList = DEFAULT_FIELD_KEY_LIST
fieldKeyList = fieldKeyList.replace(" ", "")
fieldKeyList = fieldKeyList.replace(";", ",")
fieldKeyList = fieldKeyList.split(",")
if debugTracing: logger.info(f"Debug Tracing (fieldKeyList={fieldKeyList})................")
separator = settings["zseparators"]
stash.Trace(f"(fieldKeyList={fieldKeyList})")
separator = stash.pluginSettings["zseparators"]
# ----------------------------------------------------------------------
# **********************************************************************
double_separator = separator + separator
if debugTracing: logger.info(f"Debug Tracing (PLUGIN_ARGS={PLUGIN_ARGS}) (WRAPPER_STYLES={WRAPPER_STYLES}) (POSTFIX_STYLES={POSTFIX_STYLES})................")
if debugTracing: logger.info(f"Debug Tracing (PLUGIN_ID=\"{PLUGIN_ID}\")................")
if debugTracing: logger.info("Debug Tracing................")
# Function to make GraphQL requests
def graphql_request(query, variables=None):
if debugTracing: logger.info("Debug Tracing................%s", query)
data = {'query': query}
if variables:
data['variables'] = variables
if debugTracing: logger.info("Debug Tracing................")
if debugTracing: logger.info("Debug Tracing................")
response = requests.post(endpoint, json=data)
if debugTracing: logger.info("Debug Tracing................")
return response.json()
stash.Trace(f"(WRAPPER_STYLES={WRAPPER_STYLES}) (POSTFIX_STYLES={POSTFIX_STYLES})")
# Function to replace illegal characters in filenames
def replace_illegal_characters(filename):
@@ -179,12 +114,11 @@ def should_exclude_path(scene_details):
# Function to form the new filename based on scene details and user settings
def form_filename(original_file_stem, scene_details):
if debugTracing: logger.info("Debug Tracing................")
filename_parts = []
tag_keys_added = 0
default_title = ''
if_notitle_use_org_filename = config["if_notitle_use_org_filename"]
include_keyField_if_in_name = settings["z_keyFIeldsIncludeInFileName"]
include_keyField_if_in_name = stash.pluginSettings["z_keyFIeldsIncludeInFileName"]
if if_notitle_use_org_filename:
default_title = original_file_stem
# ...................
@@ -195,44 +129,39 @@ def form_filename(original_file_stem, scene_details):
title = default_title
# ...................
if debugTracing: logger.info(f"Debug Tracing (title=\"{title}\")................")
stash.Trace(f"(title=\"{title}\")")
# Function to add tag to filename
def add_tag(tag_name):
nonlocal tag_keys_added
nonlocal filename_parts
if debugTracing: logger.info(f"Debug Tracing (tag_name={tag_name})................")
stash.Trace(f"(tag_name={tag_name})")
if max_tag_keys == -1 or (max_tag_keys is not None and tag_keys_added >= int(max_tag_keys)):
return # Skip adding more tags if the maximum limit is reached
if tag_name in excluded_tags:
if debugTracing: logger.info(f"Debug Tracing EXCLUDING (tag_name={tag_name})")
stash.Trace(f"EXCLUDING (tag_name={tag_name})")
return
# Check if the tag name is in the whitelist
if tag_whitelist == "" or tag_whitelist == None or (tag_whitelist and tag_name in tag_whitelist):
if WRAPPER_STYLES.get('tag'):
filename_parts.append(f"{WRAPPER_STYLES['tag'][0]}{tag_name}{WRAPPER_STYLES['tag'][1]}")
if debugTracing: logger.info("Debug Tracing................")
else:
filename_parts.append(tag_name)
if debugTracing: logger.info("Debug Tracing................")
tag_keys_added += 1
if debugTracing: logger.info("Debug Tracing................")
else:
logger.info(f"Skipping tag not in whitelist: {tag_name}")
if debugTracing: logger.info(f"Debug Tracing (tag_keys_added={tag_keys_added})................")
stash.Log(f"Skipping tag not in whitelist: {tag_name}")
stash.Trace(f"(tag_keys_added={tag_keys_added})")
for key in fieldKeyList:
if key == 'studio':
if settings["studioAppend"]:
if debugTracing: logger.info("Debug Tracing................")
if stash.pluginSettings["studioAppend"]:
studio_name = scene_details.get('studio', {})
if debugTracing: logger.info(f"Debug Tracing (studio_name={studio_name})................")
stash.Trace(f"(studio_name={studio_name})")
if studio_name:
studio_name = scene_details.get('studio', {}).get('name', '')
if debugTracing: logger.info(f"Debug Tracing (studio_name={studio_name})................")
stash.Trace(f"(studio_name={studio_name})")
if studio_name:
studio_name += POSTFIX_STYLES.get('studio')
if debugTracing: logger.info("Debug Tracing................")
if include_keyField_if_in_name or studio_name.lower() not in title.lower():
if WRAPPER_STYLES.get('studio'):
filename_parts.append(f"{WRAPPER_STYLES['studio'][0]}{studio_name}{WRAPPER_STYLES['studio'][1]}")
@@ -246,23 +175,21 @@ def form_filename(original_file_stem, scene_details):
else:
filename_parts.append(title)
elif key == 'performers':
if settings["performerAppend"]:
if stash.pluginSettings["performerAppend"]:
performers = '-'.join([performer.get('name', '') for performer in scene_details.get('performers', [])])
if performers:
performers += POSTFIX_STYLES.get('performers')
if debugTracing: logger.info(f"Debug Tracing (include_keyField_if_in_name={include_keyField_if_in_name})................")
stash.Trace(f"(include_keyField_if_in_name={include_keyField_if_in_name})")
if include_keyField_if_in_name or performers.lower() not in title.lower():
if debugTracing: logger.info(f"Debug Tracing (performers={performers})................")
stash.Trace(f"(performers={performers})")
if WRAPPER_STYLES.get('performers'):
filename_parts.append(f"{WRAPPER_STYLES['performers'][0]}{performers}{WRAPPER_STYLES['performers'][1]}")
else:
filename_parts.append(performers)
elif key == 'date':
scene_date = scene_details.get('date', '')
if debugTracing: logger.info("Debug Tracing................")
if scene_date:
scene_date += POSTFIX_STYLES.get('date')
if debugTracing: logger.info("Debug Tracing................")
if WRAPPER_STYLES.get('date'):
scene_date = f"{WRAPPER_STYLES['date'][0]}{scene_date}{WRAPPER_STYLES['date'][1]}"
if scene_date not in title:
@@ -310,200 +237,53 @@ def form_filename(original_file_stem, scene_details):
filename_parts.append(frame_rate)
elif key == 'galleries':
galleries = [gallery.get('title', '') for gallery in scene_details.get('galleries', [])]
if debugTracing: logger.info("Debug Tracing................")
for gallery_name in galleries:
if debugTracing: logger.info(f"Debug Tracing (include_keyField_if_in_name={include_keyField_if_in_name}) (gallery_name={gallery_name})................")
stash.Trace(f"(include_keyField_if_in_name={include_keyField_if_in_name}) (gallery_name={gallery_name})")
if include_keyField_if_in_name or gallery_name.lower() not in title.lower():
gallery_name += POSTFIX_STYLES.get('galleries')
if WRAPPER_STYLES.get('galleries'):
filename_parts.append(f"{WRAPPER_STYLES['galleries'][0]}{gallery_name}{WRAPPER_STYLES['galleries'][1]}")
if debugTracing: logger.info("Debug Tracing................")
else:
filename_parts.append(gallery_name)
if debugTracing: logger.info("Debug Tracing................")
if debugTracing: logger.info(f"Debug Tracing (gallery_name={gallery_name})................")
if debugTracing: logger.info("Debug Tracing................")
stash.Trace(f"(gallery_name={gallery_name})")
elif key == 'tags':
if settings["tagAppend"]:
if stash.pluginSettings["tagAppend"]:
tags = [tag.get('name', '') for tag in scene_details.get('tags', [])]
if debugTracing: logger.info("Debug Tracing................")
for tag_name in tags:
if debugTracing: logger.info(f"Debug Tracing (include_keyField_if_in_name={include_keyField_if_in_name}) (tag_name={tag_name})................")
stash.Trace(f"(include_keyField_if_in_name={include_keyField_if_in_name}) (tag_name={tag_name})")
if include_keyField_if_in_name or tag_name.lower() not in title.lower():
add_tag(tag_name + POSTFIX_STYLES.get('tag'))
if debugTracing: logger.info(f"Debug Tracing (tag_name={tag_name})................")
if debugTracing: logger.info("Debug Tracing................")
stash.Trace(f"(tag_name={tag_name})")
if debugTracing: logger.info(f"Debug Tracing (filename_parts={filename_parts})................")
stash.Trace(f"(filename_parts={filename_parts})")
new_filename = separator.join(filename_parts).replace(double_separator, separator)
if debugTracing: logger.info(f"Debug Tracing (new_filename={new_filename})................")
stash.Trace(f"(new_filename={new_filename})")
# Check if the scene's path matches any of the excluded paths
if exclude_paths and should_exclude_path(scene_details):
logger.info(f"Scene belongs to an excluded path. Skipping filename modification.")
stash.Log(f"Scene belongs to an excluded path. Skipping filename modification.")
return Path(scene_details['files'][0]['path']).name # Return the original filename
return replace_illegal_characters(new_filename)
def find_scene_by_id(scene_id):
query_find_scene = """
query FindScene($scene_id: ID!) {
findScene(id: $scene_id) {
id
title
date
files {
path
width
height
video_codec
frame_rate
}
galleries {
title
}
studio {
name
}
performers {
name
}
tags {
name
}
}
}
"""
scene_result = graphql_request(query_find_scene, variables={"scene_id": scene_id})
return scene_result.get('data', {}).get('findScene')
def move_or_rename_files(scene_details, new_filename, original_parent_directory):
def rename_scene(scene_id):
global exitMsg
studio_directory = None
for file_info in scene_details['files']:
path = file_info['path']
original_path = Path(path)
# Check if the file's path matches any of the excluded paths
if exclude_paths and any(original_path.match(exclude_path) for exclude_path in exclude_paths):
logger.info(f"File {path} belongs to an excluded path. Skipping modification.")
continue
new_path = original_parent_directory if not move_files else original_parent_directory / scene_details['studio']['name']
if rename_files:
new_path = new_path / (new_filename + original_path.suffix)
try:
if move_files:
if studio_directory is None:
studio_directory = original_parent_directory / scene_details['studio']['name']
studio_directory.mkdir(parents=True, exist_ok=True)
if rename_files: # Check if rename_files is True
if not dry_run:
shutil.move(original_path, new_path)
logger.info(f"{dry_run_prefix}Moved and renamed file: {path} -> {new_path}")
else:
if not dry_run:
shutil.move(original_path, new_path)
logger.info(f"{dry_run_prefix}Moved file: {path} -> {new_path}")
else:
if rename_files: # Check if rename_files is True
if not dry_run:
original_path.rename(new_path)
logger.info(f"{dry_run_prefix}Renamed file: {path} -> {new_path}")
else:
if not dry_run:
shutil.move(original_path, new_path)
logger.info(f"{dry_run_prefix}Moved file: {path} -> {new_path}")
except FileNotFoundError:
log.error(f"File not found: {path}. Skipping...")
logger.error(f"File not found: {path}. Skipping...")
exitMsg = "File not found"
continue
except OSError as e:
log.error(f"Failed to move or rename file: {path}. Error: {e}")
logger.error(f"Failed to move or rename file: {path}. Error: {e}")
exitMsg = "Failed to move or rename file"
continue
return new_path # Return the new_path variable after the loop
def perform_metadata_scan(metadata_scan_path):
metadata_scan_path_windows = metadata_scan_path.resolve().as_posix()
mutation_metadata_scan = """
mutation {
metadataScan(input: { paths: "%s" })
}
""" % metadata_scan_path_windows
if debugTracing:
logger.info(f"Attempting metadata scan mutation with path: {metadata_scan_path_windows}")
logger.info(f"Mutation string: {mutation_metadata_scan}")
graphql_request(mutation_metadata_scan)
def rename_scene(scene_id, stash_directory):
global exitMsg
scene_details = find_scene_by_id(scene_id)
if debugTracing: logger.info(f"Debug Tracing (scene_details={scene_details})................")
scene_details = stash.find_scene(scene_id)
stash.Trace(f"(scene_details1={scene_details})")
if not scene_details:
log.error(f"Scene with ID {scene_id} not found.")
logger.error(f"Scene with ID {scene_id} not found.")
return
if debugTracing: logger.info(f"Debug Tracing................")
stash.Error(f"Scene with ID {scene_id} not found.")
return None
original_file_path = scene_details['files'][0]['path']
original_parent_directory = Path(original_file_path).parent
if debugTracing: logger.info(f"Debug Tracing (original_file_path={original_file_path})................")
stash.Trace(f"(original_file_path={original_file_path})")
# Check if the scene's path matches any of the excluded paths
if exclude_paths and any(Path(original_file_path).match(exclude_path) for exclude_path in exclude_paths):
logger.info(f"Scene with ID {scene_id} belongs to an excluded path. Skipping modifications.")
return
if debugTracing: logger.info(f"Debug Tracing................")
original_path_info = {'original_file_path': original_file_path,
'original_parent_directory': original_parent_directory}
new_path_info = None
original_file_stem = Path(original_file_path).stem
original_file_name = Path(original_file_path).name
new_filename = form_filename(original_file_stem, scene_details)
newFilenameWithExt = new_filename + Path(original_file_path).suffix
if debugTracing: logger.info(f"Debug Tracing (original_file_name={original_file_name})(newFilenameWithExt={newFilenameWithExt})................")
if original_file_name == newFilenameWithExt:
logger.info(f"Nothing to do, because new file name matches original file name: (newFilenameWithExt={newFilenameWithExt})")
return
if debugTracing: logger.info(f"Debug Tracing................")
if rename_files:
new_path = original_parent_directory / (newFilenameWithExt)
new_path_info = {'new_file_path': new_path}
if debugTracing: logger.info(f"{dry_run_prefix}New filename: {new_path}")
studioName = ""
if 'studio' in scene_details and scene_details['studio'] != None and 'name' in scene_details['studio']:
studioName = scene_details['studio']['name']
if move_files and studioName != "" and original_parent_directory.name != studioName:
new_path = original_parent_directory / scene_details['studio']['name'] / (new_filename + Path(original_file_path).suffix)
new_path_info = {'new_file_path': new_path}
move_or_rename_files(scene_details, new_filename, original_parent_directory)
logger.info(f"{dry_run_prefix}Moved to directory: '{new_path}'")
# If rename_files is True, attempt renaming even if move_files is False
if rename_files:
new_file_path = original_parent_directory / (new_filename + Path(original_file_name).suffix)
if original_file_name != new_filename:
try:
if not dry_run:
os.rename(original_file_path, new_file_path)
logger.info(f"{dry_run_prefix}Renamed file: {original_file_path} -> {new_file_path}")
except Exception as e:
exitMsg = "Failed to rename file"
log.error(f"Failed to rename file: {original_file_path}. Error: {e}")
logger.error(f"Failed to rename file: {original_file_path}. Error: {e}")
metadata_scan_path = original_parent_directory
perform_metadata_scan(metadata_scan_path)
stash.Log(f"Scene with ID {scene_id} belongs to an excluded path. Skipping modifications.")
return None
original_file_stem = Path(original_file_path).stem
original_file_name = Path(original_file_path).name
new_filename = form_filename(original_file_stem, scene_details)
max_filename_length = int(config["max_filename_length"])
if len(new_filename) > max_filename_length:
extension_length = len(Path(original_file_path).suffix)
@@ -511,61 +291,61 @@ def rename_scene(scene_id, stash_directory):
truncated_filename = new_filename[:max_base_filename_length]
hash_suffix = hashlib.md5(new_filename.encode()).hexdigest()
new_filename = truncated_filename + '_' + hash_suffix + Path(original_file_path).suffix
newFilenameWithExt = new_filename + Path(original_file_path).suffix
new_file_path = f"{original_parent_directory}{os.sep}{new_filename}{Path(original_file_name).suffix}"
stash.Trace(f"(original_file_name={original_file_name})(new_file_path={new_file_path})")
if original_file_name == newFilenameWithExt or original_file_name == new_filename:
stash.Log(f"Nothing to do, because new file name matches original file name: (newFilenameWithExt={newFilenameWithExt})")
return None
targetDidExist = True if os.path.isfile(new_file_path) else False
try:
if move_files:
if not dry_run:
shutil.move(original_file_path, new_file_path)
exitMsg = f"{dry_run_prefix}Moved file to '{new_file_path}' from '{original_file_path}'"
else:
if not dry_run:
os.rename(original_file_path, new_file_path)
exitMsg = f"{dry_run_prefix}Renamed file to '{new_file_path}' from '{original_file_path}'"
except OSError as e:
exitMsg = f"Failed to move/rename file: From {original_file_path} to {new_file_path}. Error: {e}"
stash.Error(exitMsg)
if not targetDidExist and os.path.isfile(new_file_path):
if os.path.isfile(original_file_path):
os.remove(original_file_path)
pass
else:
raise
if debugTracing: logger.info(f"Debug Tracing (exitMsg={exitMsg})................")
return new_filename, original_path_info, new_path_info
stash.metadata_scan(paths=[original_parent_directory.resolve().as_posix()])
stash.Log(exitMsg)
return new_filename
# Main default function for rename scene
def rename_files_task():
if debugTracing: logger.info("Debug Tracing................")
# Execute the GraphQL query to fetch all scenes
scene_result = graphql_request(QUERY_ALL_SCENES)
if debugTracing: logger.info("Debug Tracing................")
all_scenes = scene_result.get('data', {}).get('allScenes', [])
if debugTracing: logger.info("Debug Tracing................")
scene_result = stash.get_all_scenes()
all_scenes = scene_result['allScenes']
if not all_scenes:
if debugTracing: logger.info("Debug Tracing................")
log.error("No scenes found.")
logger.error("No scenes found.")
stash.Error("No scenes found.")
exit()
if debugTracing: logger.info("Debug Tracing................")
# Find the scene with the latest updated_at timestamp
latest_scene = max(all_scenes, key=lambda scene: scene['updated_at'])
# Extract the ID of the latest scene
latest_scene_id = latest_scene.get('id')
# Read stash directory from renamefile_settings.py
stash_directory = config.get('stash_directory', '')
if debugTracing: logger.info("Debug Tracing................")
# Rename the latest scene and trigger metadata scan
new_filename = rename_scene(latest_scene_id, stash_directory)
if debugTracing: logger.info(f"Debug Tracing (exitMsg={exitMsg})................")
new_filename = rename_scene(latest_scene_id)
# Log dry run state and indicate if no changes were made
if dry_run:
log.info("Dry run: Script executed in dry run mode. No changes were made.")
logger.info("Dry run: Script executed in dry run mode. No changes were made.")
stash.Log("Dry run: Script executed in dry run mode. No changes were made.")
elif not new_filename:
logger.info("No changes were made.")
else:
logger.info(f"{exitMsg}")
stash.Log("No changes were made.")
return
def fetch_dup_filename_tags(): # Place holder for new implementation
return
if PLUGIN_ARGS_MODE == "fetch_dup_filename_tags":
fetch_dup_filename_tags()
elif PLUGIN_ARGS_MODE == "rename_files_task":
if stash.PLUGIN_TASK_NAME == "rename_files_task":
rename_files_task()
elif inputToUpdateScenePost:
rename_files_task()
if debugTracing: logger.info("\n*********************************\nEXITING ***********************\n*********************************")
stash.Trace("\n*********************************\nEXITING ***********************\n*********************************")
# ToDo: Wish List
# Add logic to update Sqlite DB on file name change, instead of perform_metadata_scan.
# Add code to get tags from duplicate filenames