mirror of
https://github.com/StuffAnThings/qbit_manage.git
synced 2025-10-09 05:18:03 +08:00
* 4.1.4-develop1 * Fixes #545 * Fixes #546 * oops forgot to check if group_tag is enabled * (fix) blu unregistered torrent message (#547) InfoHash not found. * fix broken tags check * Fixes MinSeedTimeNotReached not being applied correctly #548 * Bump pre-commit from 3.7.0 to 3.7.1 (#549) Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.7.0 to 3.7.1. - [Release notes](https://github.com/pre-commit/pre-commit/releases) - [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md) - [Commits](https://github.com/pre-commit/pre-commit/compare/v3.7.0...v3.7.1) --- updated-dependencies: - dependency-name: pre-commit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fixes exclude directory of recently deleted torrents from rem_orphaned #550 * minor debug comment update * Fixes exclude directory of recently deleted torrents from rem_orphaned #550 for those that don't use recycle bin * Fixes cross-seed bug introduced in v6 with cross-seed-data * optimize remove_empty_dirs and remove empty folders in orphaned_data * Additional blutopia unregistered_torrent status, do not delete orphaned_data root folder if it's empty * Adds additional logging for cleaning up empty folders * 4.1.4 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: bakerboy448 <55419169+bakerboy448@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
112 lines
4.6 KiB
Python
112 lines
4.6 KiB
Python
import os
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
from fnmatch import fnmatch
|
|
|
|
from modules import util
|
|
|
|
logger = util.logger
|
|
|
|
|
|
class RemoveOrphaned:
|
|
def __init__(self, qbit_manager):
|
|
self.qbt = qbit_manager
|
|
self.config = qbit_manager.config
|
|
self.client = qbit_manager.client
|
|
self.stats = 0
|
|
|
|
self.remote_dir = qbit_manager.config.remote_dir
|
|
self.root_dir = qbit_manager.config.root_dir
|
|
self.orphaned_dir = qbit_manager.config.orphaned_dir
|
|
|
|
max_workers = max(os.cpu_count() - 1, 1)
|
|
self.executor = ThreadPoolExecutor(max_workers=max_workers)
|
|
self.rem_orphaned()
|
|
self.executor.shutdown()
|
|
|
|
def rem_orphaned(self):
|
|
"""Remove orphaned files from remote directory"""
|
|
self.stats = 0
|
|
logger.separator("Checking for Orphaned Files", space=False, border=False)
|
|
torrent_files = []
|
|
orphaned_files = []
|
|
excluded_orphan_files = []
|
|
|
|
root_files = self.executor.submit(util.get_root_files, self.root_dir, self.remote_dir, self.orphaned_dir)
|
|
|
|
# Get an updated list of torrents
|
|
logger.print_line("Locating orphan files", self.config.loglevel)
|
|
torrent_list = self.qbt.get_torrents({"sort": "added_on"})
|
|
|
|
torrent_files.extend(
|
|
[
|
|
fullpath
|
|
for fullpathlist in self.executor.map(self.get_full_path_of_torrent_files, torrent_list)
|
|
for fullpath in fullpathlist
|
|
]
|
|
)
|
|
|
|
orphaned_files = set(root_files.result()) - set(torrent_files)
|
|
|
|
if self.config.orphaned["exclude_patterns"]:
|
|
logger.print_line("Processing orphan exclude patterns")
|
|
exclude_patterns = [
|
|
exclude_pattern.replace(self.remote_dir, self.root_dir)
|
|
for exclude_pattern in self.config.orphaned["exclude_patterns"]
|
|
]
|
|
excluded_orphan_files = [
|
|
file for file in orphaned_files for exclude_pattern in exclude_patterns if fnmatch(file, exclude_pattern)
|
|
]
|
|
|
|
orphaned_files = set(orphaned_files) - set(excluded_orphan_files)
|
|
|
|
if orphaned_files:
|
|
orphaned_files = sorted(orphaned_files)
|
|
os.makedirs(self.orphaned_dir, exist_ok=True)
|
|
body = []
|
|
num_orphaned = len(orphaned_files)
|
|
logger.print_line(f"{num_orphaned} Orphaned files found", self.config.loglevel)
|
|
body += logger.print_line("\n".join(orphaned_files), self.config.loglevel)
|
|
body += logger.print_line(
|
|
f"{'Not moving' if self.config.dry_run else 'Moving'} {num_orphaned} Orphaned files "
|
|
f"to {self.orphaned_dir.replace(self.remote_dir, self.root_dir)}",
|
|
self.config.loglevel,
|
|
)
|
|
|
|
attr = {
|
|
"function": "rem_orphaned",
|
|
"title": f"Removing {num_orphaned} Orphaned Files",
|
|
"body": "\n".join(body),
|
|
"orphaned_files": list(orphaned_files),
|
|
"orphaned_directory": self.orphaned_dir.replace(self.remote_dir, self.root_dir),
|
|
"total_orphaned_files": num_orphaned,
|
|
}
|
|
self.config.send_notifications(attr)
|
|
# Delete empty directories after moving orphan files
|
|
if not self.config.dry_run:
|
|
orphaned_parent_path = set(self.executor.map(self.move_orphan, orphaned_files))
|
|
logger.print_line("Removing newly empty directories", self.config.loglevel)
|
|
self.executor.map(
|
|
lambda directory: util.remove_empty_directories(directory, self.qbt.get_category_save_paths()),
|
|
orphaned_parent_path,
|
|
)
|
|
|
|
else:
|
|
logger.print_line("No Orphaned Files found.", self.config.loglevel)
|
|
|
|
def move_orphan(self, file):
|
|
src = file.replace(self.root_dir, self.remote_dir)
|
|
dest = os.path.join(self.orphaned_dir, file.replace(self.root_dir, ""))
|
|
util.move_files(src, dest, True)
|
|
return os.path.dirname(file).replace(self.root_dir, self.remote_dir)
|
|
|
|
def get_full_path_of_torrent_files(self, torrent):
|
|
torrent_files = map(lambda dict: dict.name, torrent.files)
|
|
save_path = torrent.save_path
|
|
|
|
fullpath_torrent_files = []
|
|
for file in torrent_files:
|
|
fullpath = os.path.join(save_path, file)
|
|
# Replace fullpath with \\ if qbm is running in docker (linux) but qbt is on windows
|
|
fullpath = fullpath.replace(r"/", "\\") if ":\\" in fullpath else fullpath
|
|
fullpath_torrent_files.append(fullpath)
|
|
return fullpath_torrent_files
|