mirror of
https://github.com/StuffAnThings/qbit_manage.git
synced 2025-10-09 05:18:03 +08:00
Merge pull request #37 from SamuelCook/OrphanedFilesExcludePattern
Allow file patterns to exclude from orphan detection.
This commit is contained in:
commit
00088d057f
4 changed files with 40 additions and 10 deletions
|
@ -26,6 +26,7 @@ To run the script in an interactive terminal run:
|
||||||
* Add the `tag` definition based on tracker URL
|
* Add the `tag` definition based on tracker URL
|
||||||
* Modify the `nohardlinks` by specifying your completed movies/series category to match with qBittorrent. Please ensure the `root_dir` and/or `remote_dir` is added in the `directory` section
|
* Modify the `nohardlinks` by specifying your completed movies/series category to match with qBittorrent. Please ensure the `root_dir` and/or `remote_dir` is added in the `directory` section
|
||||||
* `root_dir` needs to be defined in order to use the RecycleBin function. If optional `empty_after_x_days` is not defined then it will never empty the RecycleBin. Setting it to 0 will empty the RecycleBin immediately.
|
* `root_dir` needs to be defined in order to use the RecycleBin function. If optional `empty_after_x_days` is not defined then it will never empty the RecycleBin. Setting it to 0 will empty the RecycleBin immediately.
|
||||||
|
* Modify the `orphaned` section to define file patterns not to consider as orphans. Use this to exclude your incomplete torrents directory, or to ignore auto-generated files such as Thumbs.db.
|
||||||
* To run the script in an interactive terminal with a list of possible commands run:
|
* To run the script in an interactive terminal with a list of possible commands run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
@ -75,4 +75,13 @@ recyclebin:
|
||||||
#<OPTIONAL> empty_after_x_days var: Will automatically remove all files and folders in recycle bin after x days.
|
#<OPTIONAL> empty_after_x_days var: Will automatically remove all files and folders in recycle bin after x days.
|
||||||
# If this variable is not defined it, the RecycleBin will never be emptied.
|
# If this variable is not defined it, the RecycleBin will never be emptied.
|
||||||
# Setting this variable to 0 will delete files immediately.
|
# Setting this variable to 0 will delete files immediately.
|
||||||
empty_after_x_days: 60
|
empty_after_x_days: 60
|
||||||
|
|
||||||
|
# Orphaned files are those in the root_dir download directory that are not referenced by any active torrents.
|
||||||
|
orphaned:
|
||||||
|
# File patterns that will not be considered orphaned files. Handy for generated files that aren't part of the torrent but belong with the torrent's files
|
||||||
|
exclude_patterns:
|
||||||
|
- "**/.DS_Store"
|
||||||
|
- "**/Thumbs.db"
|
||||||
|
- "**/@eaDir"
|
||||||
|
- "/data/torrents/temp/**"
|
|
@ -8,7 +8,7 @@ directory:
|
||||||
# Do not remove these
|
# Do not remove these
|
||||||
# Cross-seed var: </your/path/here/> #Output directory of cross-seed
|
# Cross-seed var: </your/path/here/> #Output directory of cross-seed
|
||||||
# root_dir var: </your/path/here/> #Root downloads directory used to check for orphaned files, noHL, and RecycleBin.
|
# root_dir var: </your/path/here/> #Root downloads directory used to check for orphaned files, noHL, and RecycleBin.
|
||||||
# <OPTIONAL> remote_dir var: </your/path/here/> # Path of docker host mapping of root_dir.
|
# <OPTIONAL> remote_dir var: </your/path/here/> # Path of docker host mapping of root_dir.
|
||||||
# Must be set if you're running qbit_manage locally and qBittorrent/cross_seed is in a docker
|
# Must be set if you're running qbit_manage locally and qBittorrent/cross_seed is in a docker
|
||||||
cross_seed: "/your/path/here/"
|
cross_seed: "/your/path/here/"
|
||||||
root_dir: "/data/torrents/"
|
root_dir: "/data/torrents/"
|
||||||
|
@ -74,7 +74,16 @@ nohardlinks:
|
||||||
#By default the Recycle Bin will be emptied on every run of the qbit_manage script if empty_after_x_days is defined.
|
#By default the Recycle Bin will be emptied on every run of the qbit_manage script if empty_after_x_days is defined.
|
||||||
recyclebin:
|
recyclebin:
|
||||||
enabled: true
|
enabled: true
|
||||||
#<OPTIONAL> empty_after_x_days var: Will automatically remove all files and folders in recycle bin after x days. (Checks every script run)
|
#<OPTIONAL> empty_after_x_days var: Will automatically remove all files and folders in recycle bin after x days. (Checks every script run)
|
||||||
# If this variable is not defined it, the RecycleBin will never be emptied.
|
# If this variable is not defined it, the RecycleBin will never be emptied.
|
||||||
# WARNING: Setting this variable to 0 will delete all files immediately upon script run!
|
# WARNING: Setting this variable to 0 will delete all files immediately upon script run!
|
||||||
empty_after_x_days: 60
|
empty_after_x_days: 60
|
||||||
|
|
||||||
|
# Orphaned files are those in the root_dir download directory that are not referenced by any active torrents.
|
||||||
|
orphaned:
|
||||||
|
# File patterns that will not be considered orphaned files. Handy for generated files that aren't part of the torrent but belong with the torrent's files
|
||||||
|
exclude_patterns:
|
||||||
|
- "**/.DS_Store"
|
||||||
|
- "**/Thumbs.db"
|
||||||
|
- "**/@eaDir"
|
||||||
|
- "/data/torrents/temp/**"
|
|
@ -13,6 +13,7 @@ import datetime
|
||||||
import time
|
import time
|
||||||
import stat
|
import stat
|
||||||
import sys
|
import sys
|
||||||
|
import fnmatch
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from qbittorrentapi import Client
|
from qbittorrentapi import Client
|
||||||
|
@ -41,7 +42,6 @@ parser.add_argument('-tnhl', '--tag-nohardlinks', dest='tag_nohardlinks', action
|
||||||
parser.add_argument('-sr', '--skip-recycle', dest='skip_recycle', action="store_true", default=False, help='Use this to skip emptying the Reycle Bin folder.')
|
parser.add_argument('-sr', '--skip-recycle', dest='skip_recycle', action="store_true", default=False, help='Use this to skip emptying the Reycle Bin folder.')
|
||||||
parser.add_argument('-dr', '--dry-run', dest='dry_run', action="store_true", default=False, help='If you would like to see what is gonna happen but not actually move/delete or tag/categorize anything.')
|
parser.add_argument('-dr', '--dry-run', dest='dry_run', action="store_true", default=False, help='If you would like to see what is gonna happen but not actually move/delete or tag/categorize anything.')
|
||||||
parser.add_argument('-ll', '--log-level', dest='log_level', action="store", default='INFO', type=str, help='Change your log level.')
|
parser.add_argument('-ll', '--log-level', dest='log_level', action="store", default='INFO', type=str, help='Change your log level.')
|
||||||
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
@ -304,7 +304,7 @@ def set_recheck():
|
||||||
f' --Ratio vs Max Ratio: {torrent.ratio} < {torrent.max_ratio}\n'
|
f' --Ratio vs Max Ratio: {torrent.ratio} < {torrent.max_ratio}\n'
|
||||||
f' --Seeding Time vs Max Seed Time: {datetime.timedelta(seconds=torrent.seeding_time)} < {datetime.timedelta(minutes=torrent.max_seeding_time)}')
|
f' --Seeding Time vs Max Seed Time: {datetime.timedelta(seconds=torrent.seeding_time)} < {datetime.timedelta(minutes=torrent.max_seeding_time)}')
|
||||||
if torrent.ratio < torrent.max_ratio and (torrent.seeding_time < (torrent.max_seeding_time * 60)):
|
if torrent.ratio < torrent.max_ratio and (torrent.seeding_time < (torrent.max_seeding_time * 60)):
|
||||||
if dry_run:
|
if dry_run:
|
||||||
logger.dryrun(f'\n - Not Resuming {new_tag} - {torrent.name}')
|
logger.dryrun(f'\n - Not Resuming {new_tag} - {torrent.name}')
|
||||||
else:
|
else:
|
||||||
logger.info(f'\n - Resuming {new_tag} - {torrent.name}')
|
logger.info(f'\n - Resuming {new_tag} - {torrent.name}')
|
||||||
|
@ -491,7 +491,7 @@ def set_rem_unregistered():
|
||||||
'PACKS' in msg_up or \
|
'PACKS' in msg_up or \
|
||||||
'REPACKED' in msg_up or \
|
'REPACKED' in msg_up or \
|
||||||
'PACK' in msg_up or \
|
'PACK' in msg_up or \
|
||||||
'TRUMP' in msg_up
|
'TRUMP' in msg_up
|
||||||
) and x.status == 4 and 'DOWN' not in msg_up and 'UNREACHABLE' not in msg_up:
|
) and x.status == 4 and 'DOWN' not in msg_up and 'UNREACHABLE' not in msg_up:
|
||||||
logger.debug(f'Torrent counts: {t_count}')
|
logger.debug(f'Torrent counts: {t_count}')
|
||||||
logger.debug(f'msg: {t_msg}')
|
logger.debug(f'msg: {t_msg}')
|
||||||
|
@ -537,6 +537,7 @@ def set_rem_unregistered():
|
||||||
if (len(pot_unr) > 0):
|
if (len(pot_unr) > 0):
|
||||||
logger.debug(f'Potential Unregistered torrents: {pot_unr}')
|
logger.debug(f'Potential Unregistered torrents: {pot_unr}')
|
||||||
|
|
||||||
|
|
||||||
def set_rem_orphaned():
|
def set_rem_orphaned():
|
||||||
if rem_orphaned:
|
if rem_orphaned:
|
||||||
torrent_files = []
|
torrent_files = []
|
||||||
|
@ -551,13 +552,23 @@ def set_rem_orphaned():
|
||||||
for torrent in torrent_list:
|
for torrent in torrent_list:
|
||||||
for file in torrent.files:
|
for file in torrent.files:
|
||||||
torrent_files.append(os.path.join(torrent.save_path,file.name))
|
torrent_files.append(os.path.join(torrent.save_path,file.name))
|
||||||
|
|
||||||
orphaned_files = set(root_files) - set(torrent_files)
|
orphaned_files = set(root_files) - set(torrent_files)
|
||||||
orphaned_files = sorted(orphaned_files)
|
orphaned_files = sorted(orphaned_files)
|
||||||
|
|
||||||
|
excluded_orphan_files = []
|
||||||
|
if 'orphaned' in cfg and cfg["orphaned"] is not None and 'exclude_patterns' in cfg['orphaned'] and cfg['orphaned']['exclude_patterns'] != '':
|
||||||
|
exclude_patterns = cfg['orphaned']['exclude_patterns']
|
||||||
|
excluded_orphan_files = [file for file in orphaned_files for exclude_pattern in exclude_patterns if fnmatch.fnmatch(file, exclude_pattern)]
|
||||||
|
|
||||||
|
orphaned_files = set(orphaned_files) - set(excluded_orphan_files)
|
||||||
|
|
||||||
logger.debug('----------torrent files-----------')
|
logger.debug('----------torrent files-----------')
|
||||||
logger.debug("\n".join(torrent_files))
|
logger.debug("\n".join(torrent_files))
|
||||||
logger.debug('----------root_files-----------')
|
logger.debug('----------root_files-----------')
|
||||||
logger.debug("\n".join(root_files))
|
logger.debug("\n".join(root_files))
|
||||||
|
logger.debug('----------excluded_orphan_files-----------')
|
||||||
|
logger.debug("\n".join(excluded_orphan_files))
|
||||||
logger.debug('----------orphaned_files-----------')
|
logger.debug('----------orphaned_files-----------')
|
||||||
logger.debug("\n".join(orphaned_files))
|
logger.debug("\n".join(orphaned_files))
|
||||||
logger.debug('----------Deleting orphan files-----------')
|
logger.debug('----------Deleting orphan files-----------')
|
||||||
|
@ -724,7 +735,7 @@ def nohardlink(file):
|
||||||
def tor_delete_recycle(torrent):
|
def tor_delete_recycle(torrent):
|
||||||
if 'recyclebin' in cfg and cfg["recyclebin"] != None:
|
if 'recyclebin' in cfg and cfg["recyclebin"] != None:
|
||||||
if 'enabled' in cfg["recyclebin"] and cfg["recyclebin"]['enabled']:
|
if 'enabled' in cfg["recyclebin"] and cfg["recyclebin"]['enabled']:
|
||||||
tor_files = []
|
tor_files = []
|
||||||
#Define torrent files/folders
|
#Define torrent files/folders
|
||||||
for file in torrent.files:
|
for file in torrent.files:
|
||||||
tor_files.append(os.path.join(torrent.save_path,file.name))
|
tor_files.append(os.path.join(torrent.save_path,file.name))
|
||||||
|
@ -807,7 +818,7 @@ def set_empty_recycle():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
#Define global parameters
|
#Define global parameters
|
||||||
torrent_list = None
|
torrent_list = None
|
||||||
torrentdict = None
|
torrentdict = None
|
||||||
def start():
|
def start():
|
||||||
|
|
Loading…
Add table
Reference in a new issue