forked from Github/Axter-Stash
Separated example and unit test task to separate files.
This commit is contained in:
@@ -9,7 +9,13 @@ import watchdog # pip install watchdog # https://pythonhosted.org/watchdog/
|
||||
from watchdog.observers import Observer # This is also needed for event attributes
|
||||
from threading import Lock, Condition
|
||||
from multiprocessing import shared_memory
|
||||
from filemonitor_config import config # Import settings from filemonitor_config.py
|
||||
from filemonitor_config import config
|
||||
from filemonitor_task_examples import task_examples
|
||||
from filemonitor_self_unit_test import self_unit_test
|
||||
|
||||
config['task_scheduler'] = config['task_scheduler'] + task_examples['task_scheduler']
|
||||
if self_unit_test['selfUnitTest']:
|
||||
config['task_scheduler'] = config['task_scheduler'] + self_unit_test['task_scheduler']
|
||||
|
||||
CONTINUE_RUNNING_SIG = 99
|
||||
STOP_RUNNING_SIG = 32
|
||||
@@ -74,11 +80,6 @@ fileExtTypes = stash.pluginConfig['fileExtTypes'].split(",") if stash.pluginConf
|
||||
includePathChanges = stash.pluginConfig['includePathChanges'] if len(stash.pluginConfig['includePathChanges']) > 0 else stash.STASH_PATHS
|
||||
excludePathChanges = stash.pluginConfig['excludePathChanges']
|
||||
|
||||
|
||||
stash.Trace(f"(apiKey={stash.API_KEY})")
|
||||
stash.Trace(f"(includePathChanges={includePathChanges})")
|
||||
|
||||
|
||||
if stash.DRY_RUN:
|
||||
stash.Log("Dry run mode is enabled.")
|
||||
stash.Trace(f"(SCAN_MODIFIED={SCAN_MODIFIED}) (SCAN_ON_ANY_EVENT={SCAN_ON_ANY_EVENT}) (RECURSIVE={RECURSIVE})")
|
||||
@@ -88,7 +89,6 @@ StartFileMonitorAsAServiceTaskName = "Start Library Monitor Service"
|
||||
StartFileMonitorAsAPluginTaskID = "start_library_monitor"
|
||||
StartFileMonitorAsAServiceTaskID = "start_library_monitor_service"
|
||||
|
||||
|
||||
FileMonitorPluginIsOnTaskQue = stash.CALLED_AS_STASH_PLUGIN
|
||||
StopLibraryMonitorWaitingInTaskQueue = False
|
||||
JobIdInTheQue = 0
|
||||
@@ -211,25 +211,7 @@ class StashScheduler: # Stash Scheduler
|
||||
elif task['task'] == "Generate":
|
||||
result = stash.metadata_generate()
|
||||
elif task['task'] == "Backup":
|
||||
stash.LogOnce("Note: Backup task does not get listed in the Task Queue, but user can verify that it started by looking in the Stash log file as an INFO level log line.")
|
||||
result = stash.backup_database()
|
||||
maximumBackup = stash.pluginSettings['zmaximumBackups']
|
||||
stash.Trace(f"maximumBackup={maximumBackup}")
|
||||
if "maxBackups" in task:
|
||||
maximumBackup = task['maxBackups']
|
||||
stash.Trace(f"maximumBackup={maximumBackup}")
|
||||
if isinstance(maximumBackup,str):
|
||||
maximumBackup = int(maximumBackup)
|
||||
if maximumBackup < 2:
|
||||
stash.TraceOnce(f"Skipping DB backup file trim because zmaximumBackups={maximumBackup}. Value has to be greater than 1.")
|
||||
elif 'backupDirectoryPath' in stash.STASH_CONFIGURATION:
|
||||
if len(stash.STASH_CONFIGURATION['backupDirectoryPath']) < 5:
|
||||
stash.TraceOnce(f"Skipping DB backup file trim because backupDirectoryPath length is to short. Len={len(stash.STASH_CONFIGURATION['backupDirectoryPath'])}. Only support length greater than 4 characters.")
|
||||
elif os.path.exists(stash.STASH_CONFIGURATION['backupDirectoryPath']):
|
||||
stash.LogOnce(f"Checking quantity of DB backups if path {stash.STASH_CONFIGURATION['backupDirectoryPath']} exceeds {maximumBackup} backup files.")
|
||||
self.trimDbFiles(stash.STASH_CONFIGURATION['backupDirectoryPath'], maximumBackup)
|
||||
else:
|
||||
stash.TraceOnce(f"Skipping DB backup file trim because backupDirectoryPath does NOT exist. backupDirectoryPath={stash.STASH_CONFIGURATION['backupDirectoryPath']}")
|
||||
result = self.runBackupTask(task)
|
||||
elif task['task'] == "Scan":
|
||||
result = stash.metadata_scan(paths=targetPaths)
|
||||
elif task['task'] == "Auto Tag":
|
||||
@@ -261,94 +243,138 @@ class StashScheduler: # Stash Scheduler
|
||||
Msg = task['msg']
|
||||
result = stash.TraceOnce(Msg)
|
||||
elif task['task'] == "CheckStashIsRunning":
|
||||
try:
|
||||
result = stash.stash_version()
|
||||
except:
|
||||
pass
|
||||
# Note: Can not call stash.Error if Stash is not running, because that might throw another exception.
|
||||
stash.Trace("Failed to get response from Stash.")
|
||||
if platform.system() == "Windows":
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-win.exe"]
|
||||
elif platform.system() == "Darwin": # MacOS
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep} stash-macos "]
|
||||
elif platform.system().lower().startswith("linux"):
|
||||
# ToDo: Need to verify this method will work for (stash-linux-arm32v6, stash-linux-arm32v7, and stash-linux-arm64v8)
|
||||
if platform.system().lower().find("32v6") > -1:
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux-arm32v6"]
|
||||
elif platform.system().lower().find("32v7") > -1:
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux-arm32v7"]
|
||||
elif platform.system().lower().find("64v8 ") > -1:
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux-arm64v8"]
|
||||
else:
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux"]
|
||||
elif platform.system().lower().startswith("freebsd"):
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-freebsd"]
|
||||
elif 'command' not in task or task['command'] == "":
|
||||
stash.Trace("Error: Can not start Stash, because failed to determine platform OS. As a workaround, add 'command' field to this task.")
|
||||
return
|
||||
if 'command' in task and task['command'] != "":
|
||||
cmd = task['command'].replace("<stash_path>", f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}")
|
||||
args = [cmd]
|
||||
result = f"Execute process PID = {stash.ExecuteProcess(args)}"
|
||||
time.sleep(10)
|
||||
if "RunAfter" in task and len(task['RunAfter']) > 0:
|
||||
for runAfterTask in task['RunAfter']:
|
||||
self.runTask(runAfterTask)
|
||||
result = self.checkStashIsRunning(task)
|
||||
elif task['task'] == "python":
|
||||
if 'script' in task and task['script'] != "":
|
||||
script = task['script'].replace("<plugin_path>", f"{pathlib.Path(__file__).resolve().parent}{os.sep}")
|
||||
stash.Log(f"Executing python script {script}.")
|
||||
args = [script]
|
||||
if 'args' in task and len(task['args']) > 0:
|
||||
args = args + [task['args']]
|
||||
detached = True
|
||||
if 'detach' in task:
|
||||
detached = task['detach']
|
||||
result = f"Python process PID = {stash.ExecutePythonScript(args, ExecDetach=detached)}"
|
||||
else:
|
||||
stash.Error(f"Can not run task '{task['task']}', because it's missing 'script' field.")
|
||||
result = self.runPythonScript(task)
|
||||
elif task['task'] == "execute":
|
||||
if 'command' in task and task['command'] != "":
|
||||
cmd = task['command'].replace("<plugin_path>", f"{pathlib.Path(__file__).resolve().parent}{os.sep}")
|
||||
args = [cmd]
|
||||
if 'args' in task and len(task['args']) > 0:
|
||||
args = args + [task['args']]
|
||||
stash.Log(f"Executing command arguments {args}.")
|
||||
result = f"Execute process PID = {stash.ExecuteProcess(args)}"
|
||||
else:
|
||||
stash.Error(f"Can not run task '{task['task']}', because it's missing 'command' field.")
|
||||
result = self.runExecuteProcessTask(task)
|
||||
else:
|
||||
# ToDo: Add code to check if plugin is installed.
|
||||
try:
|
||||
if 'pluginId' in task and task['pluginId'] != "":
|
||||
invalidDir = False
|
||||
validDirMsg = ""
|
||||
if 'validateDir' in task and task['validateDir'] != "":
|
||||
invalidDir = True
|
||||
communityPluginPath = f"{stash.PLUGINS_PATH}{os.sep}community{os.sep}{task['validateDir']}"
|
||||
basePluginPath = f"{stash.PLUGINS_PATH}{os.sep}{task['validateDir']}"
|
||||
if os.path.exists(communityPluginPath):
|
||||
invalidDir = False
|
||||
validDirMsg = f"Valid path in {communityPluginPath}"
|
||||
elif os.path.exists(basePluginPath):
|
||||
invalidDir = False
|
||||
validDirMsg = f"Valid path in {basePluginPath}"
|
||||
if invalidDir:
|
||||
stash.Error(f"Could not run task '{task['task']}' because sub directory '{task['validateDir']}' does not exist under path '{stash.PLUGINS_PATH}'")
|
||||
else:
|
||||
stash.Trace(f"Running plugin task pluginID={task['pluginId']}, task name = {task['task']}. {validDirMsg}")
|
||||
stash.run_plugin_task(plugin_id=task['pluginId'], task_name=task['task'])
|
||||
else:
|
||||
stash.Error(f"Can not run task '{task['task']}', because it's an invalid task.")
|
||||
stash.LogOnce(f"If task '{task['task']}' is supposed to be a built-in task, check for correct task name spelling.")
|
||||
stash.LogOnce(f"If task '{task['task']}' is supposed to be a plugin, make sure to include the pluginId field in the task. task={task}")
|
||||
except Exception as e:
|
||||
stash.LogOnce(f"Failed to call plugin {task['task']} with plugin-ID {task['pluginId']}. Error: {e}")
|
||||
pass
|
||||
result = self.runPluginTask(task)
|
||||
|
||||
if result:
|
||||
stash.Trace(f"Task '{task['task']}' result={result}")
|
||||
|
||||
def runExecuteProcessTask(self, task):
|
||||
if 'command' in task and task['command'] != "":
|
||||
cmd = task['command'].replace("<plugin_path>", f"{pathlib.Path(__file__).resolve().parent}{os.sep}")
|
||||
args = [cmd]
|
||||
if 'args' in task and len(task['args']) > 0:
|
||||
args = args + [task['args']]
|
||||
stash.Log(f"Executing command arguments {args}.")
|
||||
return f"Execute process PID = {stash.ExecuteProcess(args)}"
|
||||
else:
|
||||
stash.Error(f"Can not run task '{task['task']}', because it's missing 'command' field.")
|
||||
return None
|
||||
|
||||
def runPythonScript(self, task):
|
||||
if 'script' in task and task['script'] != "":
|
||||
script = task['script'].replace("<plugin_path>", f"{pathlib.Path(__file__).resolve().parent}{os.sep}")
|
||||
stash.Log(f"Executing python script {script}.")
|
||||
args = [script]
|
||||
if 'args' in task and len(task['args']) > 0:
|
||||
args = args + [task['args']]
|
||||
detached = True
|
||||
if 'detach' in task:
|
||||
detached = task['detach']
|
||||
return f"Python process PID = {stash.ExecutePythonScript(args, ExecDetach=detached)}"
|
||||
else:
|
||||
stash.Error(f"Can not run task '{task['task']}', because it's missing 'script' field.")
|
||||
return None
|
||||
|
||||
def runPluginTask(self, task):
|
||||
# ToDo: Add code to check if plugin is installed.
|
||||
try:
|
||||
if 'pluginId' in task and task['pluginId'] != "":
|
||||
invalidDir = False
|
||||
validDirMsg = ""
|
||||
if 'validateDir' in task and task['validateDir'] != "":
|
||||
invalidDir = True
|
||||
communityPluginPath = f"{stash.PLUGINS_PATH}{os.sep}community{os.sep}{task['validateDir']}"
|
||||
basePluginPath = f"{stash.PLUGINS_PATH}{os.sep}{task['validateDir']}"
|
||||
if os.path.exists(communityPluginPath):
|
||||
invalidDir = False
|
||||
validDirMsg = f"Valid path in {communityPluginPath}"
|
||||
elif os.path.exists(basePluginPath):
|
||||
invalidDir = False
|
||||
validDirMsg = f"Valid path in {basePluginPath}"
|
||||
if invalidDir:
|
||||
stash.Error(f"Could not run task '{task['task']}' because sub directory '{task['validateDir']}' does not exist under path '{stash.PLUGINS_PATH}'")
|
||||
else:
|
||||
stash.Trace(f"Running plugin task pluginID={task['pluginId']}, task name = {task['task']}. {validDirMsg}")
|
||||
return stash.run_plugin_task(plugin_id=task['pluginId'], task_name=task['task'])
|
||||
else:
|
||||
stash.Error(f"Can not run task '{task['task']}', because it's an invalid task.")
|
||||
stash.LogOnce(f"If task '{task['task']}' is supposed to be a built-in task, check for correct task name spelling.")
|
||||
stash.LogOnce(f"If task '{task['task']}' is supposed to be a plugin, make sure to include the pluginId field in the task. task={task}")
|
||||
except Exception as e:
|
||||
stash.LogOnce(f"Failed to call plugin {task['task']} with plugin-ID {task['pluginId']}. Error: {e}")
|
||||
pass
|
||||
return None
|
||||
|
||||
def checkStashIsRunning(self, task):
|
||||
try:
|
||||
result = stash.stash_version()
|
||||
except:
|
||||
pass
|
||||
stash.Error("Failed to get response from Stash.")
|
||||
if platform.system() == "Windows":
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-win.exe"
|
||||
elif platform.system() == "Darwin": # MacOS
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep} stash-macos "
|
||||
elif platform.system().lower().startswith("linux"):
|
||||
# ToDo: Need to verify this method will work for (stash-linux-arm32v6, stash-linux-arm32v7, and stash-linux-arm64v8)
|
||||
if platform.system().lower().find("32v6") > -1:
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux-arm32v6"
|
||||
elif platform.system().lower().find("32v7") > -1:
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux-arm32v7"
|
||||
elif platform.system().lower().find("64v8 ") > -1:
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux-arm64v8"
|
||||
else:
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux"
|
||||
elif platform.system().lower().startswith("freebsd"):
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-freebsd"
|
||||
elif 'command' not in task or task['command'] == "":
|
||||
stash.Error("Can not start Stash, because failed to determine platform OS. As a workaround, add 'command' field to this task.")
|
||||
return None
|
||||
|
||||
if 'command' in task and task['command'] != "":
|
||||
cmd = task['command'].replace("<stash_path>", f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}")
|
||||
args = [cmd]
|
||||
else:
|
||||
if os.path.isfile(execPath):
|
||||
args = [execPath]
|
||||
else:
|
||||
stash.Error("Could not start Stash, because could not find executable Stash file '{execPath}'")
|
||||
return None
|
||||
result = f"Execute process PID = {stash.ExecuteProcess(args)}"
|
||||
time.sleep(10)
|
||||
if "RunAfter" in task and len(task['RunAfter']) > 0:
|
||||
for runAfterTask in task['RunAfter']:
|
||||
self.runTask(runAfterTask)
|
||||
return result
|
||||
|
||||
def runBackupTask(self, task):
|
||||
stash.LogOnce("Note: Backup task does not get listed in the Task Queue, but user can verify that it started by looking in the Stash log file as an INFO level log line.")
|
||||
result = stash.backup_database()
|
||||
maximumBackup = stash.pluginSettings['zmaximumBackups']
|
||||
stash.Trace(f"maximumBackup={maximumBackup}")
|
||||
if "maxBackups" in task:
|
||||
maximumBackup = task['maxBackups']
|
||||
stash.Trace(f"maximumBackup={maximumBackup}")
|
||||
if isinstance(maximumBackup,str):
|
||||
maximumBackup = int(maximumBackup)
|
||||
if maximumBackup < 2:
|
||||
stash.TraceOnce(f"Skipping DB backup file trim because zmaximumBackups={maximumBackup}. Value has to be greater than 1.")
|
||||
elif 'backupDirectoryPath' in stash.STASH_CONFIGURATION:
|
||||
if len(stash.STASH_CONFIGURATION['backupDirectoryPath']) < 5:
|
||||
stash.TraceOnce(f"Skipping DB backup file trim because backupDirectoryPath length is to short. Len={len(stash.STASH_CONFIGURATION['backupDirectoryPath'])}. Only support length greater than 4 characters.")
|
||||
elif os.path.exists(stash.STASH_CONFIGURATION['backupDirectoryPath']):
|
||||
stash.LogOnce(f"Checking quantity of DB backups if path {stash.STASH_CONFIGURATION['backupDirectoryPath']} exceeds {maximumBackup} backup files.")
|
||||
self.trimDbFiles(stash.STASH_CONFIGURATION['backupDirectoryPath'], maximumBackup)
|
||||
else:
|
||||
stash.TraceOnce(f"Skipping DB backup file trim because backupDirectoryPath does NOT exist. backupDirectoryPath={stash.STASH_CONFIGURATION['backupDirectoryPath']}")
|
||||
return result
|
||||
|
||||
def trimDbFiles(self, dbPath, maxFiles):
|
||||
if not os.path.exists(dbPath):
|
||||
stash.LogOnce(f"Exiting trimDbFiles, because path {dbPath} does not exists.")
|
||||
|
||||
@@ -8,7 +8,8 @@ config = {
|
||||
# The [Auto Tag] task is an example of a daily scheduled task.
|
||||
# The [Generate] task is an example of a weekly scheduled task.
|
||||
# The [Backup] task is an example of a monthly scheduled task.
|
||||
# Note: The hour section in time MUST be a two digit number, and use military time format. Example: 1PM = "13:00" and 1AM = "01:00"
|
||||
# The hour section in time MUST be a two digit number, and use military time format. Example: 1PM = "13:00" and 1AM = "01:00"
|
||||
# Note: Look at filemonitor_task_examples.py for many example task having more detailed usage.
|
||||
"task_scheduler": [
|
||||
# To create a daily task, include each day of the week for the weekday field.
|
||||
{"task" : "Auto Tag", "weekday" : "monday,tuesday,wednesday,thursday,friday,saturday,sunday", "time" : "06:00"}, # Auto Tag -> [Auto Tag] (Daily at 6AM)
|
||||
@@ -32,86 +33,10 @@ config = {
|
||||
{"task" : "Clean", "weekday" : "sunday", "time" : "01:00", "monthly" : 3}, # Maintenance -> [Clean]
|
||||
{"task" : "Clean Generated Files", "weekday" : "sunday", "time" : "03:00", "monthly" : 3}, # Maintenance -> [Clean Generated Files]
|
||||
|
||||
# The [CheckStashIsRunning] task checks if Stash is running. If it's not, it will start up stash. This task only works if FileMonitor is started as a service or in command line mode.
|
||||
# The [CheckStashIsRunning] task checks if Stash is running. If not running, it will start up stash.
|
||||
# This task only works if FileMonitor is started as a service or in command line mode.
|
||||
# For more detailed usage, see examples #C1 and #C2 in filemonitor_task_examples.py
|
||||
{"task" : "CheckStashIsRunning", "minutes" :5}, # Checks every 5 minutes
|
||||
|
||||
# Example#C1 Some OS may need the "command" field, which specifies the binary path
|
||||
{"task" : "CheckStashIsRunning", "command" : "<stash_path>stash-linux-arm64v8", "minutes" :0},
|
||||
# Example#C2 RunAfter field can be used to specify task to run after starting Stash
|
||||
{"task" : "CheckStashIsRunning", "RunAfter" : [{"task" : "Scan"},{"task" : "Backup", "maxBackup" : 0},{"task" : "Clean"}], "minutes" :0},
|
||||
|
||||
# Example#A1: Task to call call_GQL API with custom input
|
||||
{"task" : "GQL", "input" : "mutation OptimiseDatabase { optimiseDatabase }", "weekday" : "sunday", "time" : "DISABLED"}, # To enable, change "DISABLED" to valid time
|
||||
|
||||
# Example#A2: Task to call a python script. When this task is executed, the keyword <plugin_path> is replaced by filemonitor.py current directory.
|
||||
# The args field is NOT required.
|
||||
{"task" : "python", "script" : "<plugin_path>test_script_hello_world.py", "args" : "--MyArguments Hello", "weekday" : "monday", "time" : "DISABLED"}, # change "DISABLED" to valid time
|
||||
|
||||
# Example#A3: The following task types can optionally take a [paths] field. If the paths field does not exists, the paths in the Stash library is used.
|
||||
{"task" : "Scan", "paths" : [r"E:\MyVideos\downloads", r"V:\MyOtherVideos"], "weekday" : "sunday", "time" : "DISABLED"}, # Library -> [Scan]
|
||||
{"task" : "Auto Tag", "paths" : [r"E:\MyVideos\downloads", r"V:\MyOtherVideos"], "weekday" : "monday,tuesday,wednesday,thursday,friday,saturday,sunday", "time" : "DISABLED"}, # Auto Tag -> [Auto Tag]
|
||||
{"task" : "Clean", "paths" : ["E:\\MyVideos\\downloads", "V:\\MyOtherVideos"], "weekday" : "sunday", "time" : "DISABLED"}, # Generated Content-> [Generate]
|
||||
|
||||
# Example#A4: Task which calls Migrations -> [Rename generated files]
|
||||
{"task" : "RenameGeneratedFiles", "weekday" : "tuesday,thursday", "time" : "DISABLED"}, # (bi-weekly) example
|
||||
|
||||
# Example#A5: The Backup task using optional field maxBackup, which overrides the UI [Max DB Backups] value
|
||||
{"task" : "Backup", "maxBackup" : 12, "weekday" : "sunday", "time" : "DISABLED"}, # Trim the DB backup files down to 12 backup files.
|
||||
{"task" : "Backup", "maxBackup" : 0, "weekday" : "sunday", "time" : "DISABLED"}, # When used with a zero value, it will make sure no file trimming will occur no matter the value of the UI [Max DB Backups]
|
||||
|
||||
# The above weekday method is the more reliable method to schedule task, because it doesn't rely on FileMonitor running continuously (non-stop).
|
||||
|
||||
# The below examples use frequency field method which can work with minutes and hours. A zero frequency value disables the task.
|
||||
# Note: Both seconds and days are also supported for the frequency field.
|
||||
# However, seconds is mainly used for test purposes.
|
||||
# And days usage is discourage, because it only works if FileMonitor is running for X many days non-stop.
|
||||
# The below example tasks are done using hours and minutes, however any of these task types can be converted to a daily, weekly, or monthly syntax.
|
||||
|
||||
# Example#B1: The following task is the syntax used for a plugin. A plugin task requires the plugin name for the [task] field, and the plugin-ID for the [pluginId] field.
|
||||
{"task" : "PluginButtonName_Here", "pluginId" : "PluginId_Here", "hours" : 0}, # The zero frequency value makes this task disabled.
|
||||
# Example#B2: Optionally, the validateDir field can be included which is used to validate that the plugin is installed either under the plugins folder or under the plugins-community folder.
|
||||
{"task" : "PluginButtonName_Here", "pluginId" : "PluginId_Here", "validateDir" : "UsuallySameAsPluginID", "hours" : 0}, # The zero frequency value makes this task disabled.
|
||||
|
||||
# Example#B3: Task to execute a command
|
||||
{"task" : "execute", "command" : "C:\\MyPath\\HelloWorld.bat", "hours" : 0},
|
||||
|
||||
# Example#B4: Task to execute a command with optional args field, and using keyword <plugin_path>, which gets replaced with filemonitor.py current directory.
|
||||
{"task" : "execute", "command" : "<plugin_path>HelloWorld.cmd", "args" : "--name David", "minutes" : 0},
|
||||
|
||||
# Comment out **test** tasks.
|
||||
# To run test, enable all task, and start FileMonitor as a service.
|
||||
# When executed, these task should be seen in the Task Queue unless otherwise stated in comments.
|
||||
# These tasks are usually executed before updating major releases on https://github.com/David-Maisonave/Axter-Stash/blob/main/plugins/FileMonitor
|
||||
# These tasks are ALWAYS executed before updating to https://github.com/stashapp/CommunityScripts
|
||||
# MUST ToDo: Always comment out below test task before checking in this code!!!
|
||||
# {"task" : "TestBadTaskNameError", "minutes" : 1}, # Test invalid task name
|
||||
# {"task" : "execute", "minutes" : 1}, # Test invalid task (missing command)
|
||||
# {"task" : "python", "minutes" : 1}, # Test invalid task (missing scripts)
|
||||
# {"task" : "PluginWithOutID", "minutes" : 1}, # Test invalid task (missing pluginId)
|
||||
# {"task" : "execute", "command" : "", "minutes" : 1}, # Test invalid task (missing command)
|
||||
# {"task" : "python", "script" : "", "minutes" : 1}, # Test invalid task (missing scripts)
|
||||
# {"task" : "PluginWithOutID", "pluginId" : "", "minutes" : 1}, # Test invalid task (missing pluginId)
|
||||
# {"task" : "Foo","pluginId":"foo","validateDir":"foo", "minutes" : 1}, # Test invalid task (missing plugin directory)
|
||||
# {"task" : "Log", "msg" : "Testing Scheduled Log", "minutes" : 1}, # Test plugin log file
|
||||
# {"task" : "Trace", "minutes" : 1}, # Test plugin trace logging
|
||||
# {"task" : "LogOnce", "seconds" :15}, # Test LogOnce
|
||||
# {"task" : "TraceOnce", "seconds" : 5}, # Test TraceOnce
|
||||
# {"task" : "CheckStashIsRunning", "RunAfter" : [{"task" : "Scan"},{"task" : "Backup", "maxBackup" : 0},{"task" : "Clean"}], "seconds" :15}, # Test RunAfter
|
||||
# {"task" : "CheckStashIsRunning", "command" : "<stash_path>stash-win.exe", "seconds" :10}, # Check if Stash is running. If not running, start up Stash.
|
||||
# {"task" : "Generate", "weekday" : "friday", "time" : "12:03"},
|
||||
# {"task" : "Clean", "weekday" : "friday", "time" : "12:03"},
|
||||
# {"task" : "Auto Tag", "weekday" : "friday", "time" : "12:03"},
|
||||
# {"task" : "Optimise Database", "weekday" : "friday", "time" : "12:03"},
|
||||
# {"task" : "Create Tags", "pluginId" : "pathParser", "validateDir" : "pathParser", "weekday" : "friday", "time" : "12:03"}, # In task queue as -> Running plugin task: Create Tags
|
||||
# {"task" : "Scan","paths": [r"B:\_\SpecialSet", r"C:\foo"], "weekday" : "friday", "time" : "12:03"},
|
||||
# {"task" : "GQL", "input" : "mutation OptimiseDatabase { optimiseDatabase }", "weekday" : "friday", "time" : "12:03"}, # In task queue as -> Optimising database...
|
||||
# {"task" : "Clean Generated Files", "weekday" : "friday", "time" : "12:03"},
|
||||
# {"task" : "RenameGeneratedFiles", "weekday" : "friday", "time" : "12:03"}, # In task queue as -> Migrating scene hashes...
|
||||
# {"task" : "Backup", "maxBackups" : 0, "weekday" : "friday", "time" : "12:03"}, # Does NOT show up in the Task Queue. Must check STASH log file to verify run.
|
||||
# {"task" : "python", "script" : "<plugin_path>test_hello_world2.py", "weekday" : "friday", "time" : "12:03"}, # Does NOT show up in the Task Queue. Check FileMonitor log file, and look for -> Task 'python' result=???
|
||||
# {"task" : "python", "script" : "<plugin_path>test_hello_world.py", "detach" : False, "weekday" : "friday", "time" : "12:03"}, # Does NOT show up in the Task Queue. Check FileMonitor log file, and look for -> Task 'python' result=???
|
||||
# {"task" : "execute", "command" : "<plugin_path>test_hello_world2.cmd", "weekday" : "friday", "time" : "12:03"}, # Does NOT show up in the Task Queue. Check FileMonitor log file, and look for -> Task 'execute' result=???
|
||||
# {"task" : "execute", "command" : "<plugin_path>test_hello_world.bat", "args" : "--name David", "weekday" : "friday", "time" : "12:03"}, # Does NOT show up in the Task Queue. Check FileMonitor log file, and look for -> Task 'execute' result=???
|
||||
],
|
||||
|
||||
# ApiKey only needed when Stash credentials are set and while calling FileMonitor via command line.
|
||||
|
||||
42
plugins/FileMonitor/filemonitor_self_unit_test.py
Normal file
42
plugins/FileMonitor/filemonitor_self_unit_test.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# **test** tasks which are disabled by default. To enable test tasks, set selfUnitTest to True.
|
||||
# To run test, enable all task, and start FileMonitor as a service.
|
||||
# When executed, these task should be seen in the Task Queue unless otherwise stated in comments.
|
||||
# These tasks are usually executed before updating major releases on https://github.com/David-Maisonave/Axter-Stash/blob/main/plugins/FileMonitor
|
||||
# These tasks are ALWAYS executed before updating to https://github.com/stashapp/CommunityScripts
|
||||
self_unit_test = {
|
||||
"task_scheduler": [
|
||||
{"task" : "TestBadTaskNameError", "minutes" : 1}, # Test invalid task name
|
||||
{"task" : "execute", "minutes" : 1}, # Test invalid task (missing command)
|
||||
{"task" : "python", "minutes" : 1}, # Test invalid task (missing scripts)
|
||||
{"task" : "PluginWithOutID", "minutes" : 1}, # Test invalid task (missing pluginId)
|
||||
{"task" : "execute", "command" : "", "minutes" : 1}, # Test invalid task (missing command)
|
||||
{"task" : "python", "script" : "", "minutes" : 1}, # Test invalid task (missing scripts)
|
||||
{"task" : "PluginWithOutID", "pluginId" : "", "minutes" : 1}, # Test invalid task (missing pluginId)
|
||||
{"task" : "Foo","pluginId":"foo","validateDir":"foo", "minutes" : 1}, # Test invalid task (missing plugin directory)
|
||||
{"task" : "Log", "msg" : "Testing Scheduled Log", "minutes" : 1}, # Test plugin log file
|
||||
{"task" : "Trace", "minutes" : 1}, # Test plugin trace logging
|
||||
{"task" : "LogOnce", "seconds" :15}, # Test LogOnce
|
||||
{"task" : "TraceOnce", "seconds" : 5}, # Test TraceOnce
|
||||
# {"task" : "CheckStashIsRunning", "RunAfter" : [{"task" : "Scan"}], "seconds" :15}, # To test CheckStashIsRunning, kill Stash after starting FileMonitor service via following command:taskkill /F /IM "stash-win.exe"
|
||||
{"task" : "CheckStashIsRunning", "RunAfter" : [{"task" : "Scan"},{"task" : "Backup", "maxBackup" : 0},{"task" : "Clean"}], "seconds" :15}, # Test RunAfter
|
||||
{"task" : "CheckStashIsRunning", "command" : "<stash_path>stash-win.exe", "seconds" :10}, # Check if Stash is running. If not running, start up Stash.
|
||||
{"task" : "Generate", "weekday" : "friday", "time" : "12:03"},
|
||||
{"task" : "Clean", "weekday" : "friday", "time" : "12:03"},
|
||||
{"task" : "Auto Tag", "weekday" : "friday", "time" : "12:03"},
|
||||
{"task" : "Optimise Database", "weekday" : "friday", "time" : "12:03"},
|
||||
{"task" : "Create Tags", "pluginId" : "pathParser", "validateDir" : "pathParser", "weekday" : "friday", "time" : "12:03"}, # In task queue as -> Running plugin task: Create Tags
|
||||
{"task" : "Scan","paths": [r"B:\_\SpecialSet", r"C:\foo"], "weekday" : "friday", "time" : "12:03"},
|
||||
{"task" : "GQL", "input" : "mutation OptimiseDatabase { optimiseDatabase }", "weekday" : "friday", "time" : "12:03"}, # In task queue as -> Optimising database...
|
||||
{"task" : "Clean Generated Files", "weekday" : "friday", "time" : "12:03"},
|
||||
{"task" : "RenameGeneratedFiles", "weekday" : "friday", "time" : "12:03"}, # In task queue as -> Migrating scene hashes...
|
||||
{"task" : "Backup", "maxBackups" : 0, "weekday" : "friday", "time" : "12:03"}, # Does NOT show up in the Task Queue. Must check STASH log file to verify run.
|
||||
{"task" : "python", "script" : "<plugin_path>test_hello_world2.py", "weekday" : "friday", "time" : "12:03"}, # Does NOT show up in the Task Queue. Check FileMonitor log file, and look for -> Task 'python' result=???
|
||||
{"task" : "python", "script" : "<plugin_path>test_hello_world.py", "detach" : False, "weekday" : "friday", "time" : "12:03"}, # Does NOT show up in the Task Queue. Check FileMonitor log file, and look for -> Task 'python' result=???
|
||||
{"task" : "execute", "command" : "<plugin_path>test_hello_world2.cmd", "weekday" : "friday", "time" : "12:03"}, # Does NOT show up in the Task Queue. Check FileMonitor log file, and look for -> Task 'execute' result=???
|
||||
{"task" : "execute", "command" : "<plugin_path>test_hello_world.bat", "args" : "--name David", "weekday" : "friday", "time" : "12:03"}, # Does NOT show up in the Task Queue. Check FileMonitor log file, and look for -> Task 'execute' result=???
|
||||
],
|
||||
|
||||
# MUST ToDo: Always set selfUnitTest to False before checking in this code!!!
|
||||
# Enable to turn on self unit test.
|
||||
"selfUnitTest": False,
|
||||
}
|
||||
49
plugins/FileMonitor/filemonitor_task_examples.py
Normal file
49
plugins/FileMonitor/filemonitor_task_examples.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# Below are example tasks.
|
||||
# They are all disabled by default, by having zero value for time frequency, or by having "DISABLED" set for the time field.
|
||||
# To enable these tasks, set the frequency or the time value to a valid frequency or time stamp.
|
||||
task_examples = {
|
||||
"task_scheduler": [
|
||||
# Example#A1: Task to call call_GQL API with custom input
|
||||
{"task" : "GQL", "input" : "mutation OptimiseDatabase { optimiseDatabase }", "weekday" : "sunday", "time" : "DISABLED"}, # To enable, change "DISABLED" to valid time
|
||||
|
||||
# Example#A2: Task to call a python script. When this task is executed, the keyword <plugin_path> is replaced by filemonitor.py current directory.
|
||||
# The args field is NOT required.
|
||||
{"task" : "python", "script" : "<plugin_path>test_script_hello_world.py", "args" : "--MyArguments Hello", "weekday" : "monday", "time" : "DISABLED"}, # change "DISABLED" to valid time
|
||||
|
||||
# Example#A3: The following task types can optionally take a [paths] field. If the paths field does not exists, the paths in the Stash library is used.
|
||||
{"task" : "Scan", "paths" : [r"E:\MyVideos\downloads", r"V:\MyOtherVideos"], "weekday" : "sunday", "time" : "DISABLED"}, # Library -> [Scan]
|
||||
{"task" : "Auto Tag", "paths" : [r"E:\MyVideos\downloads", r"V:\MyOtherVideos"], "weekday" : "monday,tuesday,wednesday,thursday,friday,saturday,sunday", "time" : "DISABLED"}, # Auto Tag -> [Auto Tag]
|
||||
{"task" : "Clean", "paths" : ["E:\\MyVideos\\downloads", "V:\\MyOtherVideos"], "weekday" : "sunday", "time" : "DISABLED"}, # Generated Content-> [Generate]
|
||||
|
||||
# Example#A4: Task which calls Migrations -> [Rename generated files]
|
||||
{"task" : "RenameGeneratedFiles", "weekday" : "tuesday,thursday", "time" : "DISABLED"}, # (bi-weekly) example
|
||||
|
||||
# Example#A5: The Backup task using optional field maxBackup, which overrides the UI [Max DB Backups] value
|
||||
{"task" : "Backup", "maxBackup" : 12, "weekday" : "sunday", "time" : "DISABLED"}, # Trim the DB backup files down to 12 backup files.
|
||||
{"task" : "Backup", "maxBackup" : 0, "weekday" : "sunday", "time" : "DISABLED"}, # When used with a zero value, it will make sure no file trimming will occur no matter the value of the UI [Max DB Backups]
|
||||
|
||||
# The above weekday method is the more reliable method to schedule task, because it doesn't rely on FileMonitor running continuously (non-stop).
|
||||
|
||||
# The below examples use frequency field method which can work with minutes and hours. A zero frequency value disables the task.
|
||||
# Note: Both seconds and days are also supported for the frequency field.
|
||||
# However, seconds is mainly used for test purposes.
|
||||
# And days usage is discourage, because it only works if FileMonitor is running for X many days non-stop.
|
||||
# The below example tasks are done using hours and minutes, however any of these task types can be converted to a daily, weekly, or monthly syntax.
|
||||
|
||||
# Example#B1: The following task is the syntax used for a plugin. A plugin task requires the plugin name for the [task] field, and the plugin-ID for the [pluginId] field.
|
||||
{"task" : "PluginButtonName_Here", "pluginId" : "PluginId_Here", "hours" : 0}, # The zero frequency value makes this task disabled.
|
||||
# Example#B2: Optionally, the validateDir field can be included which is used to validate that the plugin is installed either under the plugins folder or under the plugins-community folder.
|
||||
{"task" : "PluginButtonName_Here", "pluginId" : "PluginId_Here", "validateDir" : "UsuallySameAsPluginID", "hours" : 0}, # The zero frequency value makes this task disabled.
|
||||
|
||||
# Example#B3: Task to execute a command
|
||||
{"task" : "execute", "command" : "C:\\MyPath\\HelloWorld.bat", "hours" : 0},
|
||||
|
||||
# Example#B4: Task to execute a command with optional args field, and using keyword <plugin_path>, which gets replaced with filemonitor.py current directory.
|
||||
{"task" : "execute", "command" : "<plugin_path>HelloWorld.cmd", "args" : "--name David", "minutes" : 0},
|
||||
|
||||
# Example#C1 Some OS may need the "command" field, which specifies the binary path
|
||||
{"task" : "CheckStashIsRunning", "command" : "<stash_path>stash-linux-arm64v8", "minutes" :0},
|
||||
# Example#C2 RunAfter field can be used to specify task to run after starting Stash
|
||||
{"task" : "CheckStashIsRunning", "RunAfter" : [{"task" : "Scan"},{"task" : "Backup", "maxBackup" : 0},{"task" : "Clean"}], "minutes" :0},
|
||||
],
|
||||
}
|
||||
Reference in New Issue
Block a user