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

Create recyclebin_recovery.py #648

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
104 changes: 104 additions & 0 deletions scripts/recyclebin_recovery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/usr/bin/python3
import argparse
import os
import shutil
import sys

import yaml


def move_files(src, dest, debug=True):
"""Move files from source to destination"""
dest_path = os.path.dirname(dest)
if debug:
print(f"From: {src} To: {dest}")
else:
if not os.path.isdir(dest_path):
os.makedirs(dest_path, exist_ok=True)
try:
shutil.move(src, dest)
except PermissionError as perm:
print(perm)
except FileNotFoundError as file:
print(f"{file} : source: {src} -> destination: {dest}")
except Exception as ex:
print(ex)


def joiner(base, add):
"""Join two paths together, just makes for less characters"""
return os.path.join(base, add)


def ls(path):
"""Kind of like bash ls, less characters"""
return os.listdir(path)


def load_config(config_path):
"""Load configuration from qbit manage's YAML config"""
with open(config_path) as file:
return yaml.safe_load(file)


if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog="QBM_Recovery",
description="Move files in the RecycleBin back into place",
epilog="Don't forget to restart qbittorrent...",
)
parser.add_argument(
"--config",
type=str,
default="../config/config.yml",
help="path to qbit_manages configuration file",
)
parser.add_argument(
"--debug",
action="store_true",
help="Print debug statements instead of taking action",
)
parser.add_argument(
"--base-dir",
type=str,
help="Base directory of the RecycleBin",
)
parser.add_argument(
"--btbackup-dir",
type=str,
help="Destination directory for BT_backup",
)
args = parser.parse_args()

# Load configuration from YAML
config = load_config(args.config)

# Retrieve directories from the config with defaults if not present
base_dir = args.base_dir or config.get("directory", {}).get("recycle_bin")
btbackup_dir = args.btbackup_dir or config.get("directory", {}).get("torrents_dir")

debug = args.debug

try:
for dir in ls(base_dir): # torrents tv movies torrents_json links
dir_path = joiner(base_dir, dir)
if dir == "torrents_json": # skip
continue
elif dir == "torrents": # move as is
for subdir in ls(dir_path):
subdir_path = joiner(dir_path, subdir)
move_files(subdir_path, btbackup_dir, debug)
elif dir == "links": # will have a subfolder
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this assumes cross-seed linkdir is base_dir + "links" and the logic within assumes flatLinking is false on v6, I don't know if these are safe assumptions to make

for subdir in ls(dir_path):
subdir_path = joiner(dir_path, subdir)
for tdir in ls(subdir_path): # the action torrent files
tdir_path = joiner(subdir_path, tdir)
move_files(tdir_path, tdir_path.replace(base_dir, ""), debug)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changing replace('/.RecycleBin', '') to replace(base_dir, '') means it wipes the whole path before the category instead of just moving up a level from the RecycleBin. To maintain the logic as I had it before we could use f'/{os.path.basename(base_dir)}'. I haven't thought through how to works if split_by_category is true though.

else: # movies tv
for subdir in ls(dir_path):
# might be a file, might be a folder
subdir_path = joiner(dir_path, subdir)
move_files(subdir_path, subdir_path.replace(base_dir, ""), debug)
print("\n\nRemember to restart Qbittorrent: docker compose restart qbittorrent")
except KeyboardInterrupt:
sys.exit(1)