mirror of
https://github.com/StuffAnThings/qbit_manage.git
synced 2025-10-27 22:48:37 +08:00
commit
00ce5c6c30
9 changed files with 91 additions and 23 deletions
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.6.0
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
|
|
@ -38,12 +38,12 @@ repos:
|
|||
name: isort (python)
|
||||
args: [--force-single-line-imports, --profile, black]
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.17.0
|
||||
rev: v3.18.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py3-plus]
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 24.8.0
|
||||
rev: 24.10.0
|
||||
hooks:
|
||||
- id: black
|
||||
language_version: python3
|
||||
|
|
@ -60,4 +60,4 @@ repos:
|
|||
entry: ./scripts/pre-commit/increase_version.sh
|
||||
language: script
|
||||
pass_filenames: false
|
||||
stages: [commit]
|
||||
stages: [pre-commit]
|
||||
|
|
|
|||
14
CHANGELOG
14
CHANGELOG
|
|
@ -1,11 +1,11 @@
|
|||
# Requirements Updated
|
||||
humanize==4.11.0
|
||||
|
||||
# New Updates
|
||||
- Adds new config option `disable_qbt_default_share_limits` to allow qbit_manage to handle share limits and disable qbittorrent's default share limits
|
||||
- Adds new config option `max_orphaned_files_to_delete` to set default safeguards against mass deletion when running remove orphaned.
|
||||
- Adds new environment variables `QBT_LOG_SIZE` and `QBT_LOG_COUNT` to customize log retention (Closes #656)
|
||||
- Adds new script to remove cross-seed tag (`scripts/remove_cross-seed_tag.py`)
|
||||
|
||||
# Bug Fixes
|
||||
- Truncates Recyclebin JSON filename when its too long. (Closes #604)
|
||||
- Uses Qbittorrent's torrent export to save .torrent files for qbittorrent version > 4.5.0 (Closes #650)
|
||||
- Include orphaned files and recycle bin in the list of folders to ignore when looking for noHL (Closes #660)
|
||||
- List orphaned files when reaches max threshold. (Closes #672)
|
||||
- Removing empty directories now ignores exclude patterns (Closes #624)
|
||||
|
||||
**Full Changelog**: https://github.com/StuffAnThings/qbit_manage/compare/v4.1.10...v4.1.11
|
||||
**Full Changelog**: https://github.com/StuffAnThings/qbit_manage/compare/v4.1.11...v4.1.12
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"master": {
|
||||
"qbit": "v4.6.6",
|
||||
"qbitapi": "2024.8.65"
|
||||
"qbit": "v5.0.0",
|
||||
"qbitapi": "2024.9.67"
|
||||
},
|
||||
"develop": {
|
||||
"qbit": "v5.0.0",
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
4.1.11
|
||||
4.1.12
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ class RemoveOrphaned:
|
|||
logger.separator("Checking for Orphaned Files", space=False, border=False)
|
||||
torrent_files = []
|
||||
orphaned_files = []
|
||||
excluded_orphan_files = []
|
||||
excluded_orphan_files = set()
|
||||
exclude_patterns = []
|
||||
|
||||
root_files = self.executor.submit(util.get_root_files, self.root_dir, self.remote_dir, self.orphaned_dir)
|
||||
|
||||
|
|
@ -54,11 +55,13 @@ class RemoveOrphaned:
|
|||
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)
|
||||
for file in orphaned_files:
|
||||
for exclude_pattern in exclude_patterns:
|
||||
if fnmatch(file, exclude_pattern):
|
||||
excluded_orphan_files.add(file)
|
||||
|
||||
orphaned_files = orphaned_files - excluded_orphan_files
|
||||
|
||||
# Check the threshold before deleting orphaned files
|
||||
max_orphaned_files_to_delete = self.config.orphaned.get("max_orphaned_files_to_delete")
|
||||
|
|
@ -69,6 +72,7 @@ class RemoveOrphaned:
|
|||
"Aborting deletion to avoid accidental data loss."
|
||||
)
|
||||
self.config.notify(e, "Remove Orphaned", False)
|
||||
logger.debug(f"Orphaned files detected: {orphaned_files}")
|
||||
logger.warning(e)
|
||||
return
|
||||
elif orphaned_files:
|
||||
|
|
@ -104,7 +108,9 @@ class RemoveOrphaned:
|
|||
orphaned_parent_path = set(self.executor.map(self.handle_orphaned_files, 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()),
|
||||
lambda directory: util.remove_empty_directories(
|
||||
directory, self.qbt.get_category_save_paths(), exclude_patterns
|
||||
),
|
||||
orphaned_parent_path,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import os
|
|||
import shutil
|
||||
import signal
|
||||
import time
|
||||
from fnmatch import fnmatch
|
||||
from pathlib import Path
|
||||
|
||||
import requests
|
||||
|
|
@ -486,7 +487,7 @@ def copy_files(src, dest):
|
|||
logger.error(ex)
|
||||
|
||||
|
||||
def remove_empty_directories(pathlib_root_dir, excluded_paths=None):
|
||||
def remove_empty_directories(pathlib_root_dir, excluded_paths=None, exclude_patterns=[]):
|
||||
"""Remove empty directories recursively, optimized version."""
|
||||
pathlib_root_dir = Path(pathlib_root_dir)
|
||||
if excluded_paths is not None:
|
||||
|
|
@ -499,6 +500,14 @@ def remove_empty_directories(pathlib_root_dir, excluded_paths=None):
|
|||
if excluded_paths and root_path in excluded_paths:
|
||||
continue
|
||||
|
||||
exclude_pattern_match = False
|
||||
for exclude_pattern in exclude_patterns:
|
||||
if fnmatch(os.path.join(root, ""), exclude_pattern):
|
||||
exclude_pattern_match = True
|
||||
break
|
||||
if exclude_pattern_match:
|
||||
continue
|
||||
|
||||
# Attempt to remove the directory if it's empty
|
||||
try:
|
||||
os.rmdir(root)
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
flake8==7.1.1
|
||||
pre-commit==3.8.0
|
||||
pre-commit==4.0.1
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
bencodepy==0.9.5
|
||||
croniter==3.0.3
|
||||
GitPython==3.1.43
|
||||
humanize==4.10.0
|
||||
humanize==4.11.0
|
||||
pytimeparse2==1.7.1
|
||||
qbittorrent-api==2024.9.67
|
||||
requests==2.32.3
|
||||
|
|
|
|||
53
scripts/remove_cross-seed_tag.py
Normal file
53
scripts/remove_cross-seed_tag.py
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
|
||||
# USES ENVIRONMENTAL VARIABLES, IF NONE ARE PRESENT WILL FALLBACK TO THE SECOND STRING
|
||||
QBIT_HOST = os.getenv("QBT_HOST", "http://localhost:8080")
|
||||
QBIT_USERNAME = os.getenv("QBT_USERNAME", "admin")
|
||||
QBIT_PASSWORD = os.getenv("QBT_PASSWORD", "YOURPASSWORD")
|
||||
|
||||
CRED = "\033[91m"
|
||||
CGREEN = "\33[32m"
|
||||
CEND = "\033[0m"
|
||||
|
||||
CROSS_SEED_TAG = "cross-seed"
|
||||
|
||||
|
||||
def split(separator, data):
|
||||
if data is None:
|
||||
return None
|
||||
else:
|
||||
return [item.strip() for item in str(data).split(separator)]
|
||||
|
||||
|
||||
try:
|
||||
from qbittorrentapi import APIConnectionError
|
||||
from qbittorrentapi import Client
|
||||
from qbittorrentapi import LoginFailed
|
||||
except ModuleNotFoundError:
|
||||
print('Error: qbittorrent-api not installed. Please install using the command "pip install qbittorrent-api"')
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
qbt_client = Client(host=QBIT_HOST, username=QBIT_USERNAME, password=QBIT_PASSWORD)
|
||||
except LoginFailed:
|
||||
raise "Qbittorrent Error: Failed to login. Invalid username/password."
|
||||
except APIConnectionError:
|
||||
raise "Qbittorrent Error: Unable to connect to the client."
|
||||
except Exception:
|
||||
raise "Qbittorrent Error: Unable to connect to the client."
|
||||
print("qBittorrent:", qbt_client.app_version())
|
||||
print("qBittorrent Web API:", qbt_client.app_web_api_version())
|
||||
print()
|
||||
|
||||
torrents_list = qbt_client.torrents.info(sort="added_on", reverse=True)
|
||||
|
||||
print("Total torrents:", len(torrents_list))
|
||||
print()
|
||||
|
||||
for torrent in torrents_list:
|
||||
torrent_tags = split(",", torrent.tags)
|
||||
|
||||
if CROSS_SEED_TAG in torrent_tags:
|
||||
print(CGREEN, "remove cross-seed tag:", torrent.name, CEND)
|
||||
torrent.remove_tags(tags=CROSS_SEED_TAG)
|
||||
Loading…
Add table
Reference in a new issue