forked from Github/Axter-Stash
1.0.0.3
### 1.0.0.3 - Added option on report to merge all metadata missing in [**Duplicate to Keep**] files. - Added cookies to report so as to remember user options for Disable Complete Confirmation **[Disable Complete Confirmation]** and **[Disable Delete Confirmation]**. - This change was needed because sometimes the browser refuse to open local URL's with params on the URL. - Using cookies also allows check options status to stay the same after refresh. - Added code to [**Advance Duplicate File Deletion Menu**] to delete based on flags.
This commit is contained in:
@@ -796,10 +796,12 @@ def writeRowToHtmlReport(fileHtmlReport, DupFile, DupFileToKeep, QtyTagForDel =
|
|||||||
# rename file
|
# rename file
|
||||||
fileHtmlReport.write(f"</p></td>")
|
fileHtmlReport.write(f"</p></td>")
|
||||||
|
|
||||||
fileHtmlReport.write("</tr>\n")
|
fileHtmlReport.write(f"</tr><!-- ::DuplicateToDelete_SceneID={DupFile['id']}::DuplicateToKeep_SceneID={DupFileToKeep['id']}:: -->\n")
|
||||||
|
|
||||||
fragmentForSceneDetails = 'id tags {id name ignore_auto_tag} groups {group {name} } performers {name} galleries {id} files {path width height duration size video_codec bit_rate frame_rate} details '
|
fragmentForSceneDetails = 'id tags {id name ignore_auto_tag} groups {group {name} } performers {name} galleries {id} files {path width height duration size video_codec bit_rate frame_rate} details '
|
||||||
htmlFileData = " paths {screenshot sprite " + htmlPreviewOrStream + "} "
|
htmlFileData = " paths {screenshot sprite " + htmlPreviewOrStream + "} "
|
||||||
|
mergeFieldData = " code director title rating100 date studio {id name} urls "
|
||||||
|
fragmentForSceneDetails += mergeFieldData + htmlFileData
|
||||||
DuplicateCandidateForDeletionList = f"{htmlReportNameFolder}{os.sep}DuplicateCandidateForDeletionList.txt"
|
DuplicateCandidateForDeletionList = f"{htmlReportNameFolder}{os.sep}DuplicateCandidateForDeletionList.txt"
|
||||||
|
|
||||||
def mangeDupFiles(merge=False, deleteDup=False, tagDuplicates=False, deleteBlacklistOnly=False, deleteLowerResAndDuration=False):
|
def mangeDupFiles(merge=False, deleteDup=False, tagDuplicates=False, deleteBlacklistOnly=False, deleteLowerResAndDuration=False):
|
||||||
@@ -835,10 +837,9 @@ def mangeDupFiles(merge=False, deleteDup=False, tagDuplicates=False, deleteBlack
|
|||||||
stash.Trace("#########################################################################")
|
stash.Trace("#########################################################################")
|
||||||
stash.Log(f"Waiting for find_duplicate_scenes_diff to return results; matchDupDistance={matchPhaseDistanceText}; significantTimeDiff={significantTimeDiff}", printTo=LOG_STASH_N_PLUGIN)
|
stash.Log(f"Waiting for find_duplicate_scenes_diff to return results; matchDupDistance={matchPhaseDistanceText}; significantTimeDiff={significantTimeDiff}", printTo=LOG_STASH_N_PLUGIN)
|
||||||
stash.startSpinningProcessBar()
|
stash.startSpinningProcessBar()
|
||||||
mergeFieldData = " code director title rating100 date studio {id name} movies {movie {id} } urls " if merge else ""
|
|
||||||
if not createHtmlReport:
|
if not createHtmlReport:
|
||||||
htmlFileData = ""
|
htmlFileData = ""
|
||||||
DupFileSets = stash.find_duplicate_scenes(matchPhaseDistance, fragment= fragmentForSceneDetails + mergeFieldData + htmlFileData)
|
DupFileSets = stash.find_duplicate_scenes(matchPhaseDistance, fragment=fragmentForSceneDetails)
|
||||||
stash.stopSpinningProcessBar()
|
stash.stopSpinningProcessBar()
|
||||||
qtyResults = len(DupFileSets)
|
qtyResults = len(DupFileSets)
|
||||||
stash.setProgressBarIter(qtyResults)
|
stash.setProgressBarIter(qtyResults)
|
||||||
@@ -1102,14 +1103,26 @@ def toJson(data):
|
|||||||
data = data.replace("\\\\\\\\", "\\\\")
|
data = data.replace("\\\\\\\\", "\\\\")
|
||||||
return json.loads(data)
|
return json.loads(data)
|
||||||
|
|
||||||
def getAnAdvanceMenuOptionSelected(taskName, target, isTagOnlyScenes, isBlackList, isGrayList, isPinkList, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, fileNotExistToDelete, compareToLess, compareToGreater):
|
def getAnAdvanceMenuOptionSelected(taskName, target, isTagOnlyScenes, tagOrFlag, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, fileNotExistToDelete, compareToLess, compareToGreater):
|
||||||
stash.Log(f"Processing taskName = {taskName}, target = {target}")
|
stash.Log(f"Processing taskName = {taskName}, target = {target}")
|
||||||
if "Blacklist" in taskName:
|
if "Blacklist" in taskName:
|
||||||
isBlackList = True
|
tagOrFlag = "Blacklist"
|
||||||
if "Graylist" in taskName:
|
if "Graylist" in taskName:
|
||||||
isGrayList = True
|
tagOrFlag = "Graylist"
|
||||||
if "Pinklist" in taskName:
|
if "Pinklist" in taskName:
|
||||||
isPinkList = True
|
tagOrFlag = "Pinklist"
|
||||||
|
if "YellowFlag" in taskName:
|
||||||
|
tagOrFlag = "YellowFlag"
|
||||||
|
if "GreenFlag" in taskName:
|
||||||
|
tagOrFlag = "GreenFlag"
|
||||||
|
if "OrangeFlag" in taskName:
|
||||||
|
tagOrFlag = "OrangeFlag"
|
||||||
|
if "CyanFlag" in taskName:
|
||||||
|
tagOrFlag = "CyanFlag"
|
||||||
|
if "PinkFlag" in taskName:
|
||||||
|
tagOrFlag = "PinkFlag"
|
||||||
|
if "RedFlag" in taskName:
|
||||||
|
tagOrFlag = "RedFlag"
|
||||||
if "Less" in taskName:
|
if "Less" in taskName:
|
||||||
compareToLess = True
|
compareToLess = True
|
||||||
if "Greater" in taskName:
|
if "Greater" in taskName:
|
||||||
@@ -1145,13 +1158,11 @@ def getAnAdvanceMenuOptionSelected(taskName, target, isTagOnlyScenes, isBlackLis
|
|||||||
isTagOnlyScenes = False
|
isTagOnlyScenes = False
|
||||||
elif "TagOnlyScenes" in taskName:
|
elif "TagOnlyScenes" in taskName:
|
||||||
isTagOnlyScenes = True
|
isTagOnlyScenes = True
|
||||||
return isTagOnlyScenes, isBlackList, isGrayList, isPinkList, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, fileNotExistToDelete, compareToLess, compareToGreater
|
return isTagOnlyScenes, tagOrFlag, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, fileNotExistToDelete, compareToLess, compareToGreater
|
||||||
|
|
||||||
def getAdvanceMenuOptionSelected(advanceMenuOptionSelected):
|
def getAdvanceMenuOptionSelected(advanceMenuOptionSelected):
|
||||||
isTagOnlyScenes = False
|
isTagOnlyScenes = False
|
||||||
isBlackList = False
|
tagOrFlag = None
|
||||||
isGrayList = False
|
|
||||||
isPinkList = False
|
|
||||||
pathToDelete = ""
|
pathToDelete = ""
|
||||||
sizeToDelete = -1
|
sizeToDelete = -1
|
||||||
durationToDelete = -1
|
durationToDelete = -1
|
||||||
@@ -1169,10 +1180,10 @@ def getAdvanceMenuOptionSelected(advanceMenuOptionSelected):
|
|||||||
if "applyCombo" in stash.PLUGIN_TASK_NAME:
|
if "applyCombo" in stash.PLUGIN_TASK_NAME:
|
||||||
jsonObject = toJson(stash.JSON_INPUT['args']['Target'])
|
jsonObject = toJson(stash.JSON_INPUT['args']['Target'])
|
||||||
for taskName in jsonObject:
|
for taskName in jsonObject:
|
||||||
isTagOnlyScenes, isBlackList, isGrayList, isPinkList, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, fileNotExistToDelete, compareToLess, compareToGreater = getAnAdvanceMenuOptionSelected(taskName, jsonObject[taskName], isTagOnlyScenes, isBlackList, isGrayList, isPinkList, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, fileNotExistToDelete, compareToLess, compareToGreater)
|
isTagOnlyScenes, tagOrFlag, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, fileNotExistToDelete, compareToLess, compareToGreater = getAnAdvanceMenuOptionSelected(taskName, jsonObject[taskName], isTagOnlyScenes, tagOrFlag, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, fileNotExistToDelete, compareToLess, compareToGreater)
|
||||||
else:
|
else:
|
||||||
return getAnAdvanceMenuOptionSelected(stash.PLUGIN_TASK_NAME, stash.JSON_INPUT['args']['Target'], isTagOnlyScenes, isBlackList, isGrayList, isPinkList, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, compareToLess, compareToGreater)
|
return getAnAdvanceMenuOptionSelected(stash.PLUGIN_TASK_NAME, stash.JSON_INPUT['args']['Target'], isTagOnlyScenes, tagOrFlag, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, compareToLess, compareToGreater)
|
||||||
return isTagOnlyScenes, isBlackList, isGrayList, isPinkList, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, fileNotExistToDelete, compareToLess, compareToGreater
|
return isTagOnlyScenes, tagOrFlag, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, fileNotExistToDelete, compareToLess, compareToGreater
|
||||||
|
|
||||||
def getScenesFromReport():
|
def getScenesFromReport():
|
||||||
stash.Log(f"Getting candidates for deletion from file {DuplicateCandidateForDeletionList}.")
|
stash.Log(f"Getting candidates for deletion from file {DuplicateCandidateForDeletionList}.")
|
||||||
@@ -1206,11 +1217,26 @@ def getFlaggedScenesFromReport(fileName, flagType):
|
|||||||
stash.Trace(f"Did not find flag {flagType}")
|
stash.Trace(f"Did not find flag {flagType}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getFlaggedScenes(ReportName = htmlReportName):
|
def getFlaggedScenes(flagType=None, ReportName = htmlReportName):
|
||||||
flaggedScenes = []
|
flaggedScenes = []
|
||||||
flagType = stash.JSON_INPUT['args']['Target']
|
if flagType == None:
|
||||||
if flagType == "green":
|
flagType = stash.JSON_INPUT['args']['Target']
|
||||||
flagType = "#00FF00"
|
if flagType == "green":
|
||||||
|
flagType = "#00FF00"
|
||||||
|
else:
|
||||||
|
if flagType == "YellowFlag":
|
||||||
|
flagType = "yellow"
|
||||||
|
if flagType == "GreenFlag":
|
||||||
|
flagType = "#00FF00"
|
||||||
|
if flagType == "OrangeFlag":
|
||||||
|
flagType = "orange"
|
||||||
|
if flagType == "CyanFlag":
|
||||||
|
flagType = "cyan"
|
||||||
|
if flagType == "PinkFlag":
|
||||||
|
flagType = "pink"
|
||||||
|
if flagType == "RedFlag":
|
||||||
|
flagType = "red"
|
||||||
|
|
||||||
stash.Debug(f"Searching for scenes with flag type {flagType}")
|
stash.Debug(f"Searching for scenes with flag type {flagType}")
|
||||||
|
|
||||||
if os.path.isfile(ReportName):
|
if os.path.isfile(ReportName):
|
||||||
@@ -1246,15 +1272,19 @@ def manageDuplicatesTaggedOrInReport(deleteScenes=False, clearTag=False, setGray
|
|||||||
if clearAllDupfileManagerTags:
|
if clearAllDupfileManagerTags:
|
||||||
excludedTags = [duplicateMarkForDeletion, duplicateWhitelistTag, excludeDupFileDeleteTag, graylistMarkForDeletion, longerDurationLowerResolution]
|
excludedTags = [duplicateMarkForDeletion, duplicateWhitelistTag, excludeDupFileDeleteTag, graylistMarkForDeletion, longerDurationLowerResolution]
|
||||||
|
|
||||||
isTagOnlyScenes, isBlackList, isGrayList, isPinkList, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, fileNotExistToDelete, compareToLess, compareToGreater = getAdvanceMenuOptionSelected(advanceMenuOptionSelected)
|
isTagOnlyScenes, tagOrFlag, pathToDelete, sizeToDelete, durationToDelete, resolutionToDelete, ratingToDelete, tagToDelete, titleToDelete, pathStrToDelete, fileNotExistToDelete, compareToLess, compareToGreater = getAdvanceMenuOptionSelected(advanceMenuOptionSelected)
|
||||||
if advanceMenuOptionSelected and deleteScenes and pathToDelete == "" and tagToDelete == "" and titleToDelete == "" and pathStrToDelete == "" and sizeToDelete == -1 and durationToDelete == -1 and resolutionToDelete == -1 and ratingToDelete == -1 and fileNotExistToDelete == False:
|
if advanceMenuOptionSelected and deleteScenes and pathToDelete == "" and tagToDelete == "" and titleToDelete == "" and pathStrToDelete == "" and sizeToDelete == -1 and durationToDelete == -1 and resolutionToDelete == -1 and ratingToDelete == -1 and fileNotExistToDelete == False:
|
||||||
stash.Error("Running advance menu option with no options enabled.")
|
stash.Error("Running advance menu option with no options enabled.")
|
||||||
return
|
return
|
||||||
|
|
||||||
flaggedScenes = None
|
flaggedScenes = None
|
||||||
flagType = None
|
flagType = None
|
||||||
if checkFlagOption:
|
if checkFlagOption or "Flag" in tagOrFlag:
|
||||||
flaggedScenes, flagType = getFlaggedScenes()
|
if checkFlagOption:
|
||||||
|
flaggedScenes, flagType = getFlaggedScenes()
|
||||||
|
else:
|
||||||
|
checkFlagOption = True
|
||||||
|
flaggedScenes, flagType = getFlaggedScenes(tagOrFlag)
|
||||||
if flaggedScenes == None or len(flaggedScenes) == 0:
|
if flaggedScenes == None or len(flaggedScenes) == 0:
|
||||||
stash.Error(f"Early exit, because found no scenes with flag {flagType}.")
|
stash.Error(f"Early exit, because found no scenes with flag {flagType}.")
|
||||||
return
|
return
|
||||||
@@ -1267,14 +1297,16 @@ def manageDuplicatesTaggedOrInReport(deleteScenes=False, clearTag=False, setGray
|
|||||||
QtyFailedQuery = 0
|
QtyFailedQuery = 0
|
||||||
stash.Debug("#########################################################################")
|
stash.Debug("#########################################################################")
|
||||||
stash.startSpinningProcessBar()
|
stash.startSpinningProcessBar()
|
||||||
if isTagOnlyScenes or (advanceMenuOptionSelected == False and checkFlagOption == False):
|
if advanceMenuOptionSelected == False and checkFlagOption == False:
|
||||||
|
isTagOnlyScenes = True
|
||||||
|
if isTagOnlyScenes:
|
||||||
stash.Log(f"Getting candidates for deletion by using tag-ID {tagId} and tag-name {tagName}; isTagOnlyScenes={isTagOnlyScenes};advanceMenuOptionSelected={advanceMenuOptionSelected}")
|
stash.Log(f"Getting candidates for deletion by using tag-ID {tagId} and tag-name {tagName}; isTagOnlyScenes={isTagOnlyScenes};advanceMenuOptionSelected={advanceMenuOptionSelected}")
|
||||||
scenes = stash.find_scenes(f={"tags": {"value":tagId, "modifier":"INCLUDES"}}, fragment='id tags {id name} files {path width height duration size video_codec bit_rate frame_rate} details title rating100')
|
scenes = stash.find_scenes(f={"tags": {"value":tagId, "modifier":"INCLUDES"}}, fragment=fragmentForSceneDetails) # Old setting 'id tags {id name} files {path width height duration size video_codec bit_rate frame_rate} details title rating100')
|
||||||
else:
|
else:
|
||||||
scenes = getScenesFromReport()
|
scenes = getScenesFromReport()
|
||||||
stash.stopSpinningProcessBar()
|
stash.stopSpinningProcessBar()
|
||||||
qtyResults = len(scenes)
|
qtyResults = len(scenes)
|
||||||
if isTagOnlyScenes or (advanceMenuOptionSelected == False and checkFlagOption == False):
|
if isTagOnlyScenes:
|
||||||
stash.Log(f"Found {qtyResults} scenes with tag ({duplicateMarkForDeletion})")
|
stash.Log(f"Found {qtyResults} scenes with tag ({duplicateMarkForDeletion})")
|
||||||
else:
|
else:
|
||||||
stash.Log(f"Found {qtyResults} scenes in report")
|
stash.Log(f"Found {qtyResults} scenes in report")
|
||||||
@@ -1321,19 +1353,24 @@ def manageDuplicatesTaggedOrInReport(deleteScenes=False, clearTag=False, setGray
|
|||||||
elif deleteScenes:
|
elif deleteScenes:
|
||||||
DupFileName = scene['files'][0]['path']
|
DupFileName = scene['files'][0]['path']
|
||||||
DupFileNameOnly = pathlib.Path(DupFileName).stem
|
DupFileNameOnly = pathlib.Path(DupFileName).stem
|
||||||
if checkFlagOption:
|
if checkFlagOption and "Flag" not in tagOrFlag:
|
||||||
if int(scene['id']) in flaggedScenes:
|
if int(scene['id']) in flaggedScenes:
|
||||||
stash.Log(f"Found {flagType} flagged candidate for deletion; Scene ID = {scene['id']}")
|
stash.Log(f"Found {flagType} flagged candidate for deletion; Scene ID = {scene['id']}")
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
elif advanceMenuOptionSelected:
|
elif advanceMenuOptionSelected:
|
||||||
if isBlackList:
|
if checkFlagOption:
|
||||||
|
if int(scene['id']) in flaggedScenes:
|
||||||
|
stash.Trace(f"Found {flagType} flag for Scene ID = {scene['id']}")
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
if tagOrFlag == "Blacklist":
|
||||||
if not stash.startsWithInList(blacklist, scene['files'][0]['path']):
|
if not stash.startsWithInList(blacklist, scene['files'][0]['path']):
|
||||||
continue
|
continue
|
||||||
if isGrayList:
|
if tagOrFlag == "Graylist":
|
||||||
if not stash.startsWithInList(graylist, scene['files'][0]['path']):
|
if not stash.startsWithInList(graylist, scene['files'][0]['path']):
|
||||||
continue
|
continue
|
||||||
if isPinkList:
|
if tagOrFlag == "Pinklist":
|
||||||
if not stash.startsWithInList(pinklist, scene['files'][0]['path']):
|
if not stash.startsWithInList(pinklist, scene['files'][0]['path']):
|
||||||
continue
|
continue
|
||||||
if pathToDelete != "":
|
if pathToDelete != "":
|
||||||
@@ -1463,11 +1500,13 @@ def removeExcludeTag():
|
|||||||
stash.Log(f"Done removing exclude tag from scene {scene}.")
|
stash.Log(f"Done removing exclude tag from scene {scene}.")
|
||||||
sys.stdout.write("{" + f"removeExcludeTag : 'complete', id: '{scene}'" + "}")
|
sys.stdout.write("{" + f"removeExcludeTag : 'complete', id: '{scene}'" + "}")
|
||||||
|
|
||||||
def getParseData(getSceneDetails1=True, getSceneDetails2=True):
|
def getParseData(getSceneDetails1=True, getSceneDetails2=True, checkIfNotSplitValue=False):
|
||||||
if 'Target' not in stash.JSON_INPUT['args']:
|
if 'Target' not in stash.JSON_INPUT['args']:
|
||||||
stash.Error(f"Could not find Target in JSON_INPUT ({stash.JSON_INPUT['args']})")
|
stash.Error(f"Could not find Target in JSON_INPUT ({stash.JSON_INPUT['args']})")
|
||||||
return None, None
|
return None, None
|
||||||
targetsSrc = stash.JSON_INPUT['args']['Target']
|
targetsSrc = stash.JSON_INPUT['args']['Target']
|
||||||
|
if checkIfNotSplitValue and ":" not in targetsSrc:
|
||||||
|
return targetsSrc, None
|
||||||
targets = targetsSrc.split(":")
|
targets = targetsSrc.split(":")
|
||||||
if len(targets) < 2:
|
if len(targets) < 2:
|
||||||
stash.Error(f"Could not get both targets from string {targetsSrc}")
|
stash.Error(f"Could not get both targets from string {targetsSrc}")
|
||||||
@@ -1483,11 +1522,44 @@ def getParseData(getSceneDetails1=True, getSceneDetails2=True):
|
|||||||
target2 = target2 + targets[2]
|
target2 = target2 + targets[2]
|
||||||
return target1, target2
|
return target1, target2
|
||||||
|
|
||||||
|
def mergeMetadataInThisFile(fileName):
|
||||||
|
stash.Debug(f"Checking report file '{fileName}' for yellow icons indicating missing metadata in DuplicateToKeep.")
|
||||||
|
lines = None
|
||||||
|
with open(fileName, 'r') as file:
|
||||||
|
lines = file.readlines()
|
||||||
|
for line in lines:
|
||||||
|
if "https://www.axter.com/images/stash/Yellow" in line: # FYI: This catches YellowGroup.png as well, even though group is not currently supported for merging
|
||||||
|
searchStrScene1 = "<!-- ::DuplicateToDelete_SceneID="
|
||||||
|
idx = line.index(searchStrScene1) + len(searchStrScene1)
|
||||||
|
scene_id1 = line[idx:]
|
||||||
|
scene_id1 = scene_id1[:scene_id1.index('::')]
|
||||||
|
searchStrScene2 = "::DuplicateToKeep_SceneID="
|
||||||
|
idx = line.index(searchStrScene2, idx) + len(searchStrScene2)
|
||||||
|
scene_id2 = line[idx:]
|
||||||
|
scene_id2 = scene_id2[:scene_id2.index('::')]
|
||||||
|
stash.Log(f"From file {fileName}, merging metadata from scene {scene_id1} to scene {scene_id2}")
|
||||||
|
stash.mergeMetadata(int(scene_id1), int(scene_id2))
|
||||||
|
updateScenesInReports(scene_id2)
|
||||||
|
|
||||||
|
def mergeMetadataForAll(ReportName = htmlReportName):
|
||||||
|
if os.path.isfile(ReportName):
|
||||||
|
mergeMetadataInThisFile(ReportName)
|
||||||
|
for x in range(2, 9999):
|
||||||
|
fileName = ReportName.replace(".html", f"_{x-1}.html")
|
||||||
|
stash.Debug(f"Checking if file '{fileName}' exist.")
|
||||||
|
if not os.path.isfile(fileName):
|
||||||
|
break
|
||||||
|
mergeMetadataInThisFile(fileName)
|
||||||
|
stash.Log(f"Done merging metadata for all scenes")
|
||||||
|
sys.stdout.write("{mergeTags : 'complete'}")
|
||||||
|
|
||||||
def mergeTags():
|
def mergeTags():
|
||||||
scene1, scene2 = getParseData()
|
scene1, scene2 = getParseData(checkIfNotSplitValue=True)
|
||||||
if scene1 == None or scene2 == None:
|
if scene1 == None or scene2 == None:
|
||||||
sys.stdout.write("{" + f"mergeTags : 'failed', id1: '{scene1}', id2: '{scene2}'" + "}")
|
if scene1 == "mergeMetadataForAll":
|
||||||
|
mergeMetadataForAll()
|
||||||
|
else:
|
||||||
|
sys.stdout.write("{" + f"mergeTags : 'failed', id1: '{scene1}', id2: '{scene2}'" + "}")
|
||||||
return
|
return
|
||||||
stash.mergeMetadata(scene1, scene2)
|
stash.mergeMetadata(scene1, scene2)
|
||||||
updateScenesInReports(scene2['id'])
|
updateScenesInReports(scene2['id'])
|
||||||
@@ -1614,8 +1686,8 @@ def updateScenesInReport(fileName, scene):
|
|||||||
elif scene1 != -1 and scene2 != -1:
|
elif scene1 != -1 and scene2 != -1:
|
||||||
break
|
break
|
||||||
if scene1 != -1 and scene2 != -1:
|
if scene1 != -1 and scene2 != -1:
|
||||||
sceneDetails1 = stash.find_scene(scene1, fragment=fragmentForSceneDetails + htmlFileData)
|
sceneDetails1 = stash.find_scene(scene1, fragment=fragmentForSceneDetails)
|
||||||
sceneDetails2 = stash.find_scene(scene2, fragment=fragmentForSceneDetails + htmlFileData)
|
sceneDetails2 = stash.find_scene(scene2, fragment=fragmentForSceneDetails)
|
||||||
if sceneDetails1 == None or sceneDetails2 == None:
|
if sceneDetails1 == None or sceneDetails2 == None:
|
||||||
stash.Error("Could not get scene details for both scene1 ({scene1}) and scene2 ({scene2}); sceneDetails1={sceneDetails1}; sceneDetails2={sceneDetails2};")
|
stash.Error("Could not get scene details for both scene1 ({scene1}) and scene2 ({scene2}); sceneDetails1={sceneDetails1}; sceneDetails2={sceneDetails2};")
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
name: DupFileManager
|
name: DupFileManager
|
||||||
description: Manages duplicate files.
|
description: Manages duplicate files.
|
||||||
version: 1.0.0.2
|
version: 1.0.0.3
|
||||||
url: https://github.com/David-Maisonave/Axter-Stash/tree/main/plugins/DupFileManager
|
url: https://github.com/David-Maisonave/Axter-Stash/tree/main/plugins/DupFileManager
|
||||||
ui:
|
ui:
|
||||||
javascript:
|
javascript:
|
||||||
|
|||||||
@@ -195,24 +195,19 @@ var OrgNextPage = null;
|
|||||||
var OrgHomePage = null;
|
var OrgHomePage = null;
|
||||||
var RemoveToKeepConfirmValue = null;
|
var RemoveToKeepConfirmValue = null;
|
||||||
var RemoveValidatePromptValue = null;
|
var RemoveValidatePromptValue = null;
|
||||||
function SetPaginateButton(){
|
const StrRemoveToKeepConfirm = "RemoveToKeepConfirm=";
|
||||||
$("#NextPage").attr("href", OrgNextPage + "?" + RemoveToKeepConfirmValue + "&" + RemoveValidatePromptValue);
|
const StrRemoveValidatePrompt = "RemoveValidatePrompt=";
|
||||||
$("#PrevPage").attr("href", OrgPrevPage + "?" + RemoveToKeepConfirmValue + "&" + RemoveValidatePromptValue);
|
|
||||||
$("#HomePage").attr("href", OrgHomePage + "?" + RemoveToKeepConfirmValue + "&" + RemoveValidatePromptValue);
|
|
||||||
$("#NextPage_Top").attr("href", OrgNextPage + "?" + RemoveToKeepConfirmValue + "&" + RemoveValidatePromptValue);
|
|
||||||
$("#PrevPage_Top").attr("href", OrgPrevPage + "?" + RemoveToKeepConfirmValue + "&" + RemoveValidatePromptValue);
|
|
||||||
$("#HomePage_Top").attr("href", OrgHomePage + "?" + RemoveToKeepConfirmValue + "&" + RemoveValidatePromptValue);
|
|
||||||
}
|
|
||||||
function SetPaginateButtonChange(){
|
function SetPaginateButtonChange(){
|
||||||
var chkBxRemoveValid = document.getElementById("RemoveValidatePrompt");
|
var chkBxRemoveValid = document.getElementById("RemoveValidatePrompt");
|
||||||
var chkBxDisableDeleteConfirm = document.getElementById("RemoveToKeepConfirm");
|
var chkBxDisableDeleteConfirm = document.getElementById("RemoveToKeepConfirm");
|
||||||
RemoveToKeepConfirmValue = "RemoveToKeepConfirm=false";
|
RemoveToKeepConfirmValue = StrRemoveToKeepConfirm + "false";
|
||||||
RemoveValidatePromptValue = "RemoveValidatePrompt=false";
|
RemoveValidatePromptValue = StrRemoveValidatePrompt + "false";
|
||||||
if (chkBxRemoveValid.checked)
|
if (chkBxRemoveValid.checked)
|
||||||
RemoveToKeepConfirmValue = "RemoveToKeepConfirm=true";
|
RemoveToKeepConfirmValue = StrRemoveToKeepConfirm + "true";
|
||||||
if (chkBxDisableDeleteConfirm.checked)
|
if (chkBxDisableDeleteConfirm.checked)
|
||||||
RemoveValidatePromptValue = "RemoveValidatePrompt=true";
|
RemoveValidatePromptValue = StrRemoveValidatePrompt + "true";
|
||||||
SetPaginateButton();
|
document.cookie = RemoveToKeepConfirmValue + "&" + RemoveValidatePromptValue + ";";
|
||||||
|
console.log("Cookies = " + document.cookie);
|
||||||
}
|
}
|
||||||
function trim(str, ch) {
|
function trim(str, ch) {
|
||||||
var start = 0, end = str.length;
|
var start = 0, end = str.length;
|
||||||
@@ -300,24 +295,49 @@ $(document).ready(function(){
|
|||||||
const queryString = window.location.search;
|
const queryString = window.location.search;
|
||||||
const urlParams = new URLSearchParams(queryString);
|
const urlParams = new URLSearchParams(queryString);
|
||||||
console.log("urlParams = " + urlParams);
|
console.log("urlParams = " + urlParams);
|
||||||
RemoveToKeepConfirmValue = "RemoveToKeepConfirm=false";
|
RemoveToKeepConfirmValue = StrRemoveToKeepConfirm + "false";
|
||||||
RemoveValidatePromptValue = "RemoveValidatePrompt=false";
|
RemoveValidatePromptValue = StrRemoveValidatePrompt + "false";
|
||||||
|
var FetchCookies = true;
|
||||||
if (urlParams.get('RemoveToKeepConfirm') != null && urlParams.get('RemoveToKeepConfirm') !== ""){
|
if (urlParams.get('RemoveToKeepConfirm') != null && urlParams.get('RemoveToKeepConfirm') !== ""){
|
||||||
RemoveToKeepConfirmValue = "RemoveToKeepConfirm=" + urlParams.get('RemoveToKeepConfirm');
|
FetchCookies = false;
|
||||||
|
RemoveToKeepConfirmValue = StrRemoveToKeepConfirm + urlParams.get('RemoveToKeepConfirm');
|
||||||
if (urlParams.get('RemoveToKeepConfirm') === "true")
|
if (urlParams.get('RemoveToKeepConfirm') === "true")
|
||||||
$( "#RemoveToKeepConfirm" ).prop("checked", true);
|
$( "#RemoveToKeepConfirm" ).prop("checked", true);
|
||||||
else
|
else
|
||||||
$( "#RemoveToKeepConfirm" ).prop("checked", false);
|
$( "#RemoveToKeepConfirm" ).prop("checked", false);
|
||||||
}
|
}
|
||||||
if (urlParams.get('RemoveValidatePrompt') != null && urlParams.get('RemoveValidatePrompt') !== ""){
|
if (urlParams.get('RemoveValidatePrompt') != null && urlParams.get('RemoveValidatePrompt') !== ""){
|
||||||
RemoveValidatePromptValue = "RemoveValidatePrompt=" + urlParams.get('RemoveValidatePrompt');
|
FetchCookies = false;
|
||||||
|
RemoveValidatePromptValue = StrRemoveValidatePrompt + urlParams.get('RemoveValidatePrompt');
|
||||||
console.log("RemoveValidatePromptValue = " + RemoveValidatePromptValue);
|
console.log("RemoveValidatePromptValue = " + RemoveValidatePromptValue);
|
||||||
if (urlParams.get('RemoveValidatePrompt') === "true")
|
if (urlParams.get('RemoveValidatePrompt') === "true")
|
||||||
$( "#RemoveValidatePrompt" ).prop("checked", true);
|
$( "#RemoveValidatePrompt" ).prop("checked", true);
|
||||||
else
|
else
|
||||||
$( "#RemoveValidatePrompt" ).prop("checked", false);
|
$( "#RemoveValidatePrompt" ).prop("checked", false);
|
||||||
}
|
}
|
||||||
SetPaginateButton();
|
if (FetchCookies){
|
||||||
|
console.log("Cookies = " + document.cookie);
|
||||||
|
var cookies = document.cookie;
|
||||||
|
if (cookies.indexOf(StrRemoveToKeepConfirm) > -1){
|
||||||
|
var idx = cookies.indexOf(StrRemoveToKeepConfirm) + StrRemoveToKeepConfirm.length;
|
||||||
|
var s = cookies.substring(idx);
|
||||||
|
console.log("StrRemoveToKeepConfirm Cookie = " + s);
|
||||||
|
if (s.startsWith("true"))
|
||||||
|
$( "#RemoveToKeepConfirm" ).prop("checked", true);
|
||||||
|
else
|
||||||
|
$( "#RemoveToKeepConfirm" ).prop("checked", false);
|
||||||
|
}
|
||||||
|
if (cookies.indexOf(StrRemoveValidatePrompt) > -1){
|
||||||
|
var idx = cookies.indexOf(StrRemoveValidatePrompt) + StrRemoveValidatePrompt.length;
|
||||||
|
var s = cookies.substring(idx);
|
||||||
|
console.log("StrRemoveValidatePrompt Cookie = " + s);
|
||||||
|
if (s.startsWith("true"))
|
||||||
|
$( "#RemoveValidatePrompt" ).prop("checked", true);
|
||||||
|
else
|
||||||
|
$( "#RemoveValidatePrompt" ).prop("checked", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetPaginateButtonChange();
|
||||||
$("button").click(function(){
|
$("button").click(function(){
|
||||||
var Mode = this.value;
|
var Mode = this.value;
|
||||||
var ActionID = this.id;
|
var ActionID = this.id;
|
||||||
@@ -386,15 +406,18 @@ $(document).ready(function(){
|
|||||||
<td>Date Created: (DateCreatedPlaceHolder)</td>
|
<td>Date Created: (DateCreatedPlaceHolder)</td>
|
||||||
</tr></table></td>
|
</tr></table></td>
|
||||||
<td><table><tr>
|
<td><table><tr>
|
||||||
<td><input type="checkbox" id="RemoveValidatePrompt" name="RemoveValidatePrompt"><label for="RemoveValidatePrompt" title="Disable notice for task completion (Popup).">Disable Complete Confirmation</label><br></td>
|
|
||||||
<td><input type="checkbox" id="RemoveToKeepConfirm" name="RemoveToKeepConfirm"><label for="RemoveToKeepConfirm" title="Disable confirmation prompts for delete scenes">Disable Delete Confirmation</label><br></td>
|
|
||||||
<td>
|
<td>
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<button id="AdvanceMenu" title="View advance menu for tagged duplicates." name="AdvanceMenu">Advance Menu <i class="fa fa-caret-down"></i></button>
|
<button id="AdvanceMenu" name="AdvanceMenu">Menu <i class="fa fa-caret-down"></i></button>
|
||||||
<div class="dropdown-content">
|
<div class="dropdown-content">
|
||||||
<div><button type="button" id="clear_duplicate_tags_task" value="clear_duplicate_tags_task" title="Remove duplicate (_DuplicateMarkForDeletion_?) tag from all scenes. This action make take a few minutes to complete.">Remove All Scenes Tags</button></div>
|
<div><button id="AdvanceMenu" title="Open [Advance Duplicate File Deletion Menu] on a new tab in the browser." name="AdvanceMenu">Advance Duplicate File Deletion Menu</i></button></div>
|
||||||
|
<div style="height:2px;width:220px;border-width:0;color:gray;background-color:gray;">_</div>
|
||||||
|
<div><button type="button" id="mergeMetadataForAll" value="mergeTags" title="Merge scene metadata from [Duplicate to Delete] to [Duplicate to Keep]. This action make take a few minutes to complete.">Merge Tags, Performers, and Galleries</button></div>
|
||||||
|
<div><button type="button" id="clear_duplicate_tags_task" value="clear_duplicate_tags_task" title="Remove duplicate (_DuplicateMarkForDeletion_?) tag from all scenes. This action make take a few minutes to complete.">Remove Scenes Dup Tags</button></div>
|
||||||
|
<div style="height:2px;width:220px;border-width:0;color:gray;background-color:gray;">_</div>
|
||||||
<div><button type="button" id="fileNotExistToDelete" value="Tagged" title="Delete tagged duplicates for which file does NOT exist.">Delete Tagged Files That do Not Exist</button></div>
|
<div><button type="button" id="fileNotExistToDelete" value="Tagged" title="Delete tagged duplicates for which file does NOT exist.">Delete Tagged Files That do Not Exist</button></div>
|
||||||
<div><button type="button" id="fileNotExistToDelete" value="Report" title="Delete duplicate candidate files in report for which file does NOT exist.">Delete Files That do Not Exist in Report</button></div>
|
<div><button type="button" id="fileNotExistToDelete" value="Report" title="Delete duplicate candidate files in report for which file does NOT exist.">Delete Files That do Not Exist in Report</button></div>
|
||||||
|
<div style="height:2px;width:220px;border-width:0;color:gray;background-color:gray;">_</div>
|
||||||
<div><button type="button" id="clearAllSceneFlags" value="clearAllSceneFlags" title="Remove flags from report for all scenes, except for deletion flag.">Clear All Scene Flags</button></div>
|
<div><button type="button" id="clearAllSceneFlags" value="clearAllSceneFlags" title="Remove flags from report for all scenes, except for deletion flag.">Clear All Scene Flags</button></div>
|
||||||
<div><button title="Delete all yellow flagged scenes in report." value="deleteSceneYellowFlag" id="yellow" style="background-color:yellow" >Delete All Yellow Flagged Scenes</button></div>
|
<div><button title="Delete all yellow flagged scenes in report." value="deleteSceneYellowFlag" id="yellow" style="background-color:yellow" >Delete All Yellow Flagged Scenes</button></div>
|
||||||
<div><button title="Delete all green flagged scenes in report." value="deleteSceneGreenFlag" id="green" style="background-color:#00FF00" >Delete All Green Flagged Scenes</button></div>
|
<div><button title="Delete all green flagged scenes in report." value="deleteSceneGreenFlag" id="green" style="background-color:#00FF00" >Delete All Green Flagged Scenes</button></div>
|
||||||
@@ -406,6 +429,9 @@ $(document).ready(function(){
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
<td><input type="checkbox" id="RemoveValidatePrompt" name="RemoveValidatePrompt"><label for="RemoveValidatePrompt" title="Disable notice for task completion (Popup).">Disable Complete Confirmation</label><br></td>
|
||||||
|
<td><input type="checkbox" id="RemoveToKeepConfirm" name="RemoveToKeepConfirm"><label for="RemoveToKeepConfirm" title="Disable confirmation prompts for delete scenes">Disable Delete Confirmation</label><br></td>
|
||||||
|
|
||||||
</tr></table></td>
|
</tr></table></td>
|
||||||
</tr></table></center>
|
</tr></table></center>
|
||||||
<h2>Stash Duplicate Scenes Report (MatchTypePlaceHolder)</h2>\n""",
|
<h2>Stash Duplicate Scenes Report (MatchTypePlaceHolder)</h2>\n""",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# DupFileManager: Ver 1.0.0.2 (By David Maisonave)
|
# DupFileManager: Ver 1.0.0.3 (By David Maisonave)
|
||||||
|
|
||||||
DupFileManager is a [Stash](https://github.com/stashapp/stash) plugin which manages duplicate files in the Stash system.
|
DupFileManager is a [Stash](https://github.com/stashapp/stash) plugin which manages duplicate files in the Stash system.
|
||||||
It has both **task** and **tools-UI** components.
|
It has both **task** and **tools-UI** components.
|
||||||
@@ -103,6 +103,7 @@ That's it!!!
|
|||||||
|
|
||||||
### Future Planned Features
|
### Future Planned Features
|
||||||
- Add logic to merge performers and galaries seperatly from tag merging on report. Planned for 1.5.0 Version.
|
- Add logic to merge performers and galaries seperatly from tag merging on report. Planned for 1.5.0 Version.
|
||||||
|
- Add code to report to make it when the report updates the screen (due to tag merging), it stays in the same row position. Planned for 1.5.0 Version.
|
||||||
- Add logic to merge group metadata when selecting merge option on report. Planned for 2.0.0 Version.
|
- Add logic to merge group metadata when selecting merge option on report. Planned for 2.0.0 Version.
|
||||||
- Add advanced menu directly to the Settings->Tools menu. Planned for 2.0.0 Version.
|
- Add advanced menu directly to the Settings->Tools menu. Planned for 2.0.0 Version.
|
||||||
- Add report directly to the Settings->Tools menu. Planned for 2.0.0 Version.
|
- Add report directly to the Settings->Tools menu. Planned for 2.0.0 Version.
|
||||||
|
|||||||
@@ -256,8 +256,8 @@ $(document).ready(function(){
|
|||||||
Param += "\"" + "pathStrToDelete" + Blacklist + "\":\"" + $("#pathStrToDeleteText").val().replace("\\", "\\\\") + "\", ";
|
Param += "\"" + "pathStrToDelete" + Blacklist + "\":\"" + $("#pathStrToDeleteText").val().replace("\\", "\\\\") + "\", ";
|
||||||
if ($("#fileNotExistCheck").prop('checked'))
|
if ($("#fileNotExistCheck").prop('checked'))
|
||||||
Param += "\"" + "fileNotExistToDelete" + Blacklist + "\":\"true\", ";
|
Param += "\"" + "fileNotExistToDelete" + Blacklist + "\":\"true\", ";
|
||||||
if ($("#DupTagOnlyCheck_MultiOption").prop('checked'))
|
if ($("#tagOrFlagCombobox").val() !== "")
|
||||||
Param += "\"" + "TagOnlyScenes" + Blacklist + "\":\"true\", ";
|
Param += "\"" + $("#tagOrFlagCombobox").val() + Blacklist + "\":\"true\", ";
|
||||||
Param += '}';
|
Param += '}';
|
||||||
Param = Param.replace(', }', '}');
|
Param = Param.replace(', }', '}');
|
||||||
if (Param === "{}")
|
if (Param === "{}")
|
||||||
@@ -321,7 +321,21 @@ function DeleteDupInPath(){
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><label title="When enabled, operations only apply to scenes which have the special tag _DuplicateMarkForDeletion_?" for="DupTagOnlyCheck">Apply action only to scenes with <b>_DuplicateMarkForDeletion_?</b> tag:</label><input title="When enabled, operations only apply to scenes which have the special tag _DuplicateMarkForDeletion_?" type="checkbox" id="DupTagOnlyCheck" name="DupTagOnlyCheck" value="true"></td>
|
<td><label title="When enabled, operations only apply to scenes which have the special tag _DuplicateMarkForDeletion_?" for="DupTagOnlyCheck">Apply action only to scenes with <b>_DuplicateMarkForDeletion_?</b> tag:</label><input title="When enabled, operations only apply to scenes which have the special tag _DuplicateMarkForDeletion_?" type="checkbox" id="DupTagOnlyCheck" name="DupTagOnlyCheck" value="true"></td>
|
||||||
<td><label title="When enabled, Multi-Options operations only apply to scenes which have the special tag _DuplicateMarkForDeletion_?" for="DupTagOnlyCheck_MultiOption">Dup Tag:</label><input title="When enabled, Multi-Options operations only apply to scenes which have the special tag _DuplicateMarkForDeletion_?" type="checkbox" id="DupTagOnlyCheck_MultiOption" name="DupTagOnlyCheck" value="true"></td>
|
<td>
|
||||||
|
<label for="tagOrFlagCombobox">TagOrFlag:</label>
|
||||||
|
<select id="tagOrFlagCombobox" name="tagOrFlagCombobox">
|
||||||
|
<option value="" selected="selected"></option>
|
||||||
|
<option value="TagOnlyScenes" title="When selected, Multi-Options operations only apply to scenes which have the special tag _DuplicateMarkForDeletion_?">Dup Tag</option>
|
||||||
|
<option value="YellowFlag" style="background-color:Yellow;" title="When selected, Multi-Options operations only apply to scenes with [Yellow] fag.">Yellow Flag</option>
|
||||||
|
<option value="GreenFlag" style="background-color:#00FF00;" title="When selected, Multi-Options operations only apply to scenes with [Green] fag.">Green Flag</option>
|
||||||
|
<option value="OrangeFlag" style="background-color:Orange;" title="When selected, Multi-Options operations only apply to scenes with [Orange] fag.">Orange Flag</option>
|
||||||
|
<option value="CyanFlag" style="background-color:Cyan;" title="When selected, Multi-Options operations only apply to scenes with [Cyan] fag.">Cyan Flag</option>
|
||||||
|
<option value="PinkFlag" style="background-color:Pink;" title="When selected, Multi-Options operations only apply to scenes with [Pink] fag.">Pink Flag</option>
|
||||||
|
<option value="RedFlag" style="background-color:Red;" title="When selected, Multi-Options operations only apply to scenes with [Red] fag.">Red Flag</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><form id="pathToDeleteForm" action="javascript:DeleteDupInPath();" target="_self">
|
<td><form id="pathToDeleteForm" action="javascript:DeleteDupInPath();" target="_self">
|
||||||
|
|||||||
@@ -36,3 +36,9 @@
|
|||||||
- If data for associated icon are the same, then both icons are black or blue (the default color).
|
- If data for associated icon are the same, then both icons are black or blue (the default color).
|
||||||
- If [**duplicate to keep**] is missing data that is in [**candidate to delete**], than [**candidate to delete**] gets a yellow icon.
|
- If [**duplicate to keep**] is missing data that is in [**candidate to delete**], than [**candidate to delete**] gets a yellow icon.
|
||||||
- If [**candidate to delete**] is missing data that is in [**duplicate to keep**], than [**duplicate to keep**] gets a pink icon.
|
- If [**candidate to delete**] is missing data that is in [**duplicate to keep**], than [**duplicate to keep**] gets a pink icon.
|
||||||
|
### 1.0.0.3
|
||||||
|
- Added option on report to merge all metadata missing in [**Duplicate to Keep**] files.
|
||||||
|
- Added cookies to report so as to remember user options for Disable Complete Confirmation **[Disable Complete Confirmation]** and **[Disable Delete Confirmation]**.
|
||||||
|
- This change was needed because sometimes the browser refuse to open local URL's with params on the URL.
|
||||||
|
- Using cookies also allows check options status to stay the same after refresh.
|
||||||
|
- Added code to [**Advance Duplicate File Deletion Menu**] to delete based on flags.
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ class StashPluginHelper(StashInterface):
|
|||||||
stopProcessBarSpin = True
|
stopProcessBarSpin = True
|
||||||
updateProgressbarOnIter = 0
|
updateProgressbarOnIter = 0
|
||||||
currentProgressbarIteration = 0
|
currentProgressbarIteration = 0
|
||||||
|
galleryNamesCache = {}
|
||||||
|
|
||||||
class OS_Type(IntEnum):
|
class OS_Type(IntEnum):
|
||||||
WINDOWS = 1
|
WINDOWS = 1
|
||||||
@@ -773,6 +774,14 @@ class StashPluginHelper(StashInterface):
|
|||||||
errMsg = f"Exception calling [updateScene]. Will retry; count({i}); Error: {e}\nTraceBack={tb}"
|
errMsg = f"Exception calling [updateScene]. Will retry; count({i}); Error: {e}\nTraceBack={tb}"
|
||||||
time.sleep(sleepSecondsBetweenRetry)
|
time.sleep(sleepSecondsBetweenRetry)
|
||||||
|
|
||||||
|
# getGalleryName uses a cache so it doesn't have to hit the server for the same ID.
|
||||||
|
def getGalleryName(self, gallery_id, refreshCache=False):
|
||||||
|
if refreshCache:
|
||||||
|
self.galleryNamesCache = {}
|
||||||
|
if gallery_id not in self.galleryNamesCache:
|
||||||
|
self.galleryNamesCache[gallery_id] = self.find_gallery(gallery_id)
|
||||||
|
return self.galleryNamesCache[gallery_id]
|
||||||
|
|
||||||
def runPlugin(self, plugin_id, task_mode=None, args:dict={}, asyn=False):
|
def runPlugin(self, plugin_id, task_mode=None, args:dict={}, asyn=False):
|
||||||
"""Runs a plugin operation.
|
"""Runs a plugin operation.
|
||||||
The operation is run immediately and does not use the job queue.
|
The operation is run immediately and does not use the job queue.
|
||||||
@@ -986,6 +995,8 @@ class mergeMetadata: # A class to merge scene metadata from source scene to dest
|
|||||||
self.mergeItems('tags', 'tag_ids', [], excludeName=self.excludeMergeTags)
|
self.mergeItems('tags', 'tag_ids', [], excludeName=self.excludeMergeTags)
|
||||||
self.mergeItems('performers', 'performer_ids', [])
|
self.mergeItems('performers', 'performer_ids', [])
|
||||||
self.mergeItems('galleries', 'gallery_ids', [])
|
self.mergeItems('galleries', 'gallery_ids', [])
|
||||||
|
# ToDo: Firgure out how to merge groups
|
||||||
|
# self.mergeItems('groups', 'group_ids')
|
||||||
# Looks like movies has been removed from new Stash version
|
# Looks like movies has been removed from new Stash version
|
||||||
# self.mergeItems('movies', 'movies', [])
|
# self.mergeItems('movies', 'movies', [])
|
||||||
self.mergeItems('urls', listToAdd=self.destData['urls'], NotStartWith=self.stash.STASH_URL)
|
self.mergeItems('urls', listToAdd=self.destData['urls'], NotStartWith=self.stash.STASH_URL)
|
||||||
@@ -1020,9 +1031,13 @@ class mergeMetadata: # A class to merge scene metadata from source scene to dest
|
|||||||
if item not in self.destData[fieldName]:
|
if item not in self.destData[fieldName]:
|
||||||
if NotStartWith == None or not item.startswith(NotStartWith):
|
if NotStartWith == None or not item.startswith(NotStartWith):
|
||||||
if excludeName == None or item['name'] not in excludeName:
|
if excludeName == None or item['name'] not in excludeName:
|
||||||
if fieldName == 'movies':
|
if fieldName == 'groups':
|
||||||
listToAdd += [{"movie_id" : item['movie']['id'], "scene_index" : item['scene_index']}]
|
# listToAdd += [{"group_id" : item['group']['id'], "group_name" : item['group']['name']}]
|
||||||
dataAdded += f"{item['movie']['id']} "
|
listToAdd += [item['group']['id']]
|
||||||
|
dataAdded += f"{item['group']['id']} "
|
||||||
|
# elif fieldName == 'movies':
|
||||||
|
# listToAdd += [{"movie_id" : item['movie']['id'], "scene_index" : item['scene_index']}]
|
||||||
|
# dataAdded += f"{item['movie']['id']} "
|
||||||
elif updateFieldName == None:
|
elif updateFieldName == None:
|
||||||
listToAdd += [item]
|
listToAdd += [item]
|
||||||
dataAdded += f"{item} "
|
dataAdded += f"{item} "
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ class StashPluginHelper(StashInterface):
|
|||||||
stopProcessBarSpin = True
|
stopProcessBarSpin = True
|
||||||
updateProgressbarOnIter = 0
|
updateProgressbarOnIter = 0
|
||||||
currentProgressbarIteration = 0
|
currentProgressbarIteration = 0
|
||||||
|
galleryNamesCache = {}
|
||||||
|
|
||||||
class OS_Type(IntEnum):
|
class OS_Type(IntEnum):
|
||||||
WINDOWS = 1
|
WINDOWS = 1
|
||||||
@@ -773,6 +774,14 @@ class StashPluginHelper(StashInterface):
|
|||||||
errMsg = f"Exception calling [updateScene]. Will retry; count({i}); Error: {e}\nTraceBack={tb}"
|
errMsg = f"Exception calling [updateScene]. Will retry; count({i}); Error: {e}\nTraceBack={tb}"
|
||||||
time.sleep(sleepSecondsBetweenRetry)
|
time.sleep(sleepSecondsBetweenRetry)
|
||||||
|
|
||||||
|
# getGalleryName uses a cache so it doesn't have to hit the server for the same ID.
|
||||||
|
def getGalleryName(self, gallery_id, refreshCache=False):
|
||||||
|
if refreshCache:
|
||||||
|
self.galleryNamesCache = {}
|
||||||
|
if gallery_id not in self.galleryNamesCache:
|
||||||
|
self.galleryNamesCache[gallery_id] = self.find_gallery(gallery_id)
|
||||||
|
return self.galleryNamesCache[gallery_id]
|
||||||
|
|
||||||
def runPlugin(self, plugin_id, task_mode=None, args:dict={}, asyn=False):
|
def runPlugin(self, plugin_id, task_mode=None, args:dict={}, asyn=False):
|
||||||
"""Runs a plugin operation.
|
"""Runs a plugin operation.
|
||||||
The operation is run immediately and does not use the job queue.
|
The operation is run immediately and does not use the job queue.
|
||||||
@@ -986,6 +995,8 @@ class mergeMetadata: # A class to merge scene metadata from source scene to dest
|
|||||||
self.mergeItems('tags', 'tag_ids', [], excludeName=self.excludeMergeTags)
|
self.mergeItems('tags', 'tag_ids', [], excludeName=self.excludeMergeTags)
|
||||||
self.mergeItems('performers', 'performer_ids', [])
|
self.mergeItems('performers', 'performer_ids', [])
|
||||||
self.mergeItems('galleries', 'gallery_ids', [])
|
self.mergeItems('galleries', 'gallery_ids', [])
|
||||||
|
# ToDo: Firgure out how to merge groups
|
||||||
|
# self.mergeItems('groups', 'group_ids')
|
||||||
# Looks like movies has been removed from new Stash version
|
# Looks like movies has been removed from new Stash version
|
||||||
# self.mergeItems('movies', 'movies', [])
|
# self.mergeItems('movies', 'movies', [])
|
||||||
self.mergeItems('urls', listToAdd=self.destData['urls'], NotStartWith=self.stash.STASH_URL)
|
self.mergeItems('urls', listToAdd=self.destData['urls'], NotStartWith=self.stash.STASH_URL)
|
||||||
@@ -1020,9 +1031,13 @@ class mergeMetadata: # A class to merge scene metadata from source scene to dest
|
|||||||
if item not in self.destData[fieldName]:
|
if item not in self.destData[fieldName]:
|
||||||
if NotStartWith == None or not item.startswith(NotStartWith):
|
if NotStartWith == None or not item.startswith(NotStartWith):
|
||||||
if excludeName == None or item['name'] not in excludeName:
|
if excludeName == None or item['name'] not in excludeName:
|
||||||
if fieldName == 'movies':
|
if fieldName == 'groups':
|
||||||
listToAdd += [{"movie_id" : item['movie']['id'], "scene_index" : item['scene_index']}]
|
# listToAdd += [{"group_id" : item['group']['id'], "group_name" : item['group']['name']}]
|
||||||
dataAdded += f"{item['movie']['id']} "
|
listToAdd += [item['group']['id']]
|
||||||
|
dataAdded += f"{item['group']['id']} "
|
||||||
|
# elif fieldName == 'movies':
|
||||||
|
# listToAdd += [{"movie_id" : item['movie']['id'], "scene_index" : item['scene_index']}]
|
||||||
|
# dataAdded += f"{item['movie']['id']} "
|
||||||
elif updateFieldName == None:
|
elif updateFieldName == None:
|
||||||
listToAdd += [item]
|
listToAdd += [item]
|
||||||
dataAdded += f"{item} "
|
dataAdded += f"{item} "
|
||||||
|
|||||||
Reference in New Issue
Block a user