Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add safety check to repair #32

Closed
18 changes: 18 additions & 0 deletions repair.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def parseInterval(intervalStr):
parser.add_argument('--run-interval', type=str, default=repair['runInterval'], help='Optional interval in smart format (e.g. 1w2d3h4m5s) to run the repair process.')
parser.add_argument('--mode', type=str, choices=['symlink', 'file'], default='symlink', help='Choose repair mode: `symlink` or `file`. `symlink` to repair broken symlinks and `file` to repair missing files.')
parser.add_argument('--include-unmonitored', action='store_true', help='Include unmonitored media in the repair process')
parser.add_argument('--safety-check-script', type=str, default=repair['safetyCheckScript'], help='Python code to be evaluated and return boolean for whether torrent mount is working or not. mountTorrentsPath will be replaced by Realdebrid/Torbox mount path.')
args = parser.parse_args()

_print = print
Expand All @@ -54,6 +55,14 @@ def print(*values: object):
print(f"Invalid interval format for run interval: {args.run_interval}")
exit(1)

def safety_check(mountTorrentsPath):
try:
safety_check_passed = eval(args.safety_check_script, {"os": os, "mountTorrentsPath": mountTorrentsPath})
return safety_check_passed
except Exception as e:
print(f"Error checking torrent mount or evaluating safety check script [{safety_check_script}] for mount path [{mountTorrentsPath}] : exception: {e}")
return False

def main():
print("Collecting media...")
sonarr = Sonarr()
Expand All @@ -67,6 +76,15 @@ def main():
getItems = lambda media, childId: arr.getFiles(media=media, childId=childId) if args.mode == 'symlink' else arr.getHistory(media=media, childId=childId, includeGrandchildDetails=True)
childrenIds = media.childrenIds if args.include_unmonitored else media.monitoredChildrenIds

# perform a "Safety check" to make sure that the torrents folder is mounted to prevent deleting everything in *arrs
# we do this inside of the loop because the mount could drop at any time; so, best to check with each iteration
djsecrist marked this conversation as resolved.
Show resolved Hide resolved
if ((realdebrid['enabled'] and not safety_check(realdebrid['mountTorrentsPath'])) or (torbox['enabled'] and not safety_check(torbox['mountTorrentsPath']))):
print(f"Safety check failed: couldn't verify torrent folder is mounted")
discordError(f"[{args.mode}] An error occurred while processing {media.title}: Safety check failed: couldn't verify torrent folder is mounted")
if repairIntervalSeconds > 0:
time.sleep(repairIntervalSeconds)
continue

for childId in childrenIds:
brokenItems = []
childItems = list(getItems(media=media, childId=childId))
Expand Down
3 changes: 2 additions & 1 deletion shared/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ def stringEnvParser(value):

repair = {
'repairInterval': env.string('REPAIR_REPAIR_INTERVAL', default=None),
'runInterval': env.string('REPAIR_RUN_INTERVAL', default=None)
'runInterval': env.string('REPAIR_RUN_INTERVAL', default=None),
'safetyCheckScript': env.string('SAFETY_CHECK_SCRIPT', default='len([name for name in os.listdir(mountTorrentsPath) if os.path.isdir(os.path.join(mountTorrentsPath, name))]) > 0')
}

plexHeaders = {
Expand Down