mirror of
https://github.com/StuffAnThings/qbit_manage.git
synced 2025-09-13 00:24:45 +08:00
refactor remove_orphaned
This commit is contained in:
parent
5cfb0cd4b3
commit
89d9188d9d
3 changed files with 107 additions and 93 deletions
102
modules/core/remove_orphaned.py
Normal file
102
modules/core/remove_orphaned.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
import os
|
||||
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
|
||||
|
||||
self.rem_orphaned()
|
||||
|
||||
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 = []
|
||||
root_files = []
|
||||
orphaned_files = []
|
||||
excluded_orphan_files = []
|
||||
orphaned_parent_path = set()
|
||||
|
||||
if self.remote_dir != self.root_dir:
|
||||
root_files = [
|
||||
os.path.join(path.replace(self.remote_dir, self.root_dir), name)
|
||||
for path, subdirs, files in os.walk(self.remote_dir)
|
||||
for name in files
|
||||
if self.orphaned_dir.replace(self.remote_dir, self.root_dir) not in path
|
||||
]
|
||||
else:
|
||||
root_files = [
|
||||
os.path.join(path, name)
|
||||
for path, subdirs, files in os.walk(self.root_dir)
|
||||
for name in files
|
||||
if self.orphaned_dir.replace(self.root_dir, self.remote_dir) not in path
|
||||
]
|
||||
|
||||
# Get an updated list of torrents
|
||||
torrent_list = self.qbt.get_torrents({"sort": "added_on"})
|
||||
for torrent in torrent_list:
|
||||
for file in torrent.files:
|
||||
fullpath = os.path.join(torrent.save_path, file.name)
|
||||
# Replace fullpath with \\ if qbm is running in docker (linux) but qbt is on windows
|
||||
fullpath = fullpath.replace(r"/", "\\") if ":\\" in fullpath else fullpath
|
||||
torrent_files.append(fullpath)
|
||||
|
||||
orphaned_files = set(root_files) - set(torrent_files)
|
||||
orphaned_files = sorted(orphaned_files)
|
||||
|
||||
if self.config.orphaned["exclude_patterns"]:
|
||||
exclude_patterns = 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.replace(self.remote_dir, self.root_dir))
|
||||
]
|
||||
|
||||
orphaned_files = set(orphaned_files) - set(excluded_orphan_files)
|
||||
|
||||
if 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"{'Did not move' if self.config.dry_run else 'Moved'} {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
|
||||
logger.info("Cleaning up any empty directories...")
|
||||
if not self.config.dry_run:
|
||||
for file in orphaned_files:
|
||||
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)
|
||||
orphaned_parent_path.add(os.path.dirname(file).replace(self.root_dir, self.remote_dir))
|
||||
for parent_path in orphaned_parent_path:
|
||||
util.remove_empty_directories(parent_path, "**/*")
|
||||
else:
|
||||
logger.print_line("No Orphaned Files found.", self.config.loglevel)
|
|
@ -2,7 +2,6 @@
|
|||
import os
|
||||
import sys
|
||||
from datetime import timedelta
|
||||
from fnmatch import fnmatch
|
||||
|
||||
from qbittorrentapi import APIConnectionError
|
||||
from qbittorrentapi import Client
|
||||
|
@ -564,92 +563,6 @@ class Qbt:
|
|||
logger.warning(e)
|
||||
return category
|
||||
|
||||
def rem_orphaned(self):
|
||||
"""Remove orphaned files from remote directory"""
|
||||
orphaned = 0
|
||||
if self.config.commands["rem_orphaned"]:
|
||||
logger.separator("Checking for Orphaned Files", space=False, border=False)
|
||||
torrent_files = []
|
||||
root_files = []
|
||||
orphaned_files = []
|
||||
excluded_orphan_files = []
|
||||
orphaned_parent_path = set()
|
||||
remote_path = self.config.remote_dir
|
||||
root_path = self.config.root_dir
|
||||
orphaned_path = self.config.orphaned_dir
|
||||
if remote_path != root_path:
|
||||
root_files = [
|
||||
os.path.join(path.replace(remote_path, root_path), name)
|
||||
for path, subdirs, files in os.walk(remote_path)
|
||||
for name in files
|
||||
if orphaned_path.replace(remote_path, root_path) not in path
|
||||
]
|
||||
else:
|
||||
root_files = [
|
||||
os.path.join(path, name)
|
||||
for path, subdirs, files in os.walk(root_path)
|
||||
for name in files
|
||||
if orphaned_path.replace(root_path, remote_path) not in path
|
||||
]
|
||||
|
||||
# Get an updated list of torrents
|
||||
torrent_list = self.get_torrents({"sort": "added_on"})
|
||||
for torrent in torrent_list:
|
||||
for file in torrent.files:
|
||||
fullpath = os.path.join(torrent.save_path, file.name)
|
||||
# Replace fullpath with \\ if qbm is running in docker (linux) but qbt is on windows
|
||||
fullpath = fullpath.replace(r"/", "\\") if ":\\" in fullpath else fullpath
|
||||
torrent_files.append(fullpath)
|
||||
|
||||
orphaned_files = set(root_files) - set(torrent_files)
|
||||
orphaned_files = sorted(orphaned_files)
|
||||
|
||||
if self.config.orphaned["exclude_patterns"]:
|
||||
exclude_patterns = 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.replace(remote_path, root_path))
|
||||
]
|
||||
|
||||
orphaned_files = set(orphaned_files) - set(excluded_orphan_files)
|
||||
|
||||
if orphaned_files:
|
||||
os.makedirs(orphaned_path, 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"{'Did not move' if self.config.dry_run else 'Moved'} {num_orphaned} Orphaned files "
|
||||
f"to {orphaned_path.replace(remote_path,root_path)}",
|
||||
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": orphaned_path.replace(remote_path, root_path),
|
||||
"total_orphaned_files": num_orphaned,
|
||||
}
|
||||
self.config.send_notifications(attr)
|
||||
# Delete empty directories after moving orphan files
|
||||
logger.info("Cleaning up any empty directories...")
|
||||
if not self.config.dry_run:
|
||||
for file in orphaned_files:
|
||||
src = file.replace(root_path, remote_path)
|
||||
dest = os.path.join(orphaned_path, file.replace(root_path, ""))
|
||||
util.move_files(src, dest, True)
|
||||
orphaned_parent_path.add(os.path.dirname(file).replace(root_path, remote_path))
|
||||
for parent_path in orphaned_parent_path:
|
||||
util.remove_empty_directories(parent_path, "**/*")
|
||||
else:
|
||||
logger.print_line("No Orphaned Files found.", self.config.loglevel)
|
||||
return orphaned
|
||||
|
||||
def tor_delete_recycle(self, torrent, info):
|
||||
"""Move torrent to recycle bin"""
|
||||
if self.config.recyclebin["enabled"]:
|
||||
|
|
|
@ -293,6 +293,7 @@ from modules.core.remove_unregistered import RemoveUnregistered # noqa
|
|||
from modules.core.cross_seed import CrossSeed # noqa
|
||||
from modules.core.recheck import ReCheck # noqa
|
||||
from modules.core.tag_nohardlinks import TagNoHardLinks # noqa
|
||||
from modules.core.remove_orphaned import RemoveOrphaned # noqa
|
||||
|
||||
|
||||
def my_except_hook(exctype, value, tbi):
|
||||
|
@ -428,16 +429,14 @@ def start():
|
|||
stats["deleted_contents"] += no_hardlinks.stats_deleted_contents
|
||||
|
||||
# Remove Orphaned Files
|
||||
num_orphaned = cfg.qbt.rem_orphaned()
|
||||
stats["orphaned"] += num_orphaned
|
||||
if cfg.commands["rem_orphaned"]:
|
||||
stats["orphaned"] += RemoveOrphaned(qbit_manager).stats
|
||||
|
||||
# Empty RecycleBin
|
||||
recycle_emptied = cfg.cleanup_dirs("Recycle Bin")
|
||||
stats["recycle_emptied"] += recycle_emptied
|
||||
stats["recycle_emptied"] += cfg.cleanup_dirs("Recycle Bin")
|
||||
|
||||
# Empty Orphaned Directory
|
||||
orphaned_emptied = cfg.cleanup_dirs("Orphaned Data")
|
||||
stats["orphaned_emptied"] += orphaned_emptied
|
||||
stats["orphaned_emptied"] += cfg.cleanup_dirs("Orphaned Data")
|
||||
|
||||
if stats["categorized"] > 0:
|
||||
stats_summary.append(f"Total Torrents Categorized: {stats['categorized']}")
|
||||
|
|
Loading…
Add table
Reference in a new issue