qbit_manage/modules/qbittorrent.py

426 lines
21 KiB
Python
Raw Normal View History

"""Qbittorrent Module"""
2022-10-29 23:19:09 +08:00
import os
import sys
from qbittorrentapi import Client
from qbittorrentapi import LoginFailed
from qbittorrentapi import NotFound404Error
from qbittorrentapi import TrackerStatus
2022-10-29 23:19:09 +08:00
from qbittorrentapi import Version
from modules import util
2023-04-01 01:26:16 +08:00
from modules.util import Failed
from modules.util import list_in_text
2023-04-11 08:50:55 +08:00
from modules.util import TorrentMessages
logger = util.logger
2021-12-29 01:19:58 +08:00
class Qbt:
"""
Qbittorrent Class
"""
2023-04-01 01:26:16 +08:00
SUPPORTED_VERSION = Version.latest_supported_app_version()
MIN_SUPPORTED_VERSION = "v4.3.0"
TORRENT_DICT_COMMANDS = ["recheck", "cross_seed", "rem_unregistered", "tag_tracker_error", "tag_nohardlinks", "share_limits"]
2023-04-01 01:26:16 +08:00
def __init__(self, config, params):
self.config = config
self.host = params["host"]
self.username = params["username"]
self.password = params["password"]
logger.secret(self.username)
logger.secret(self.password)
2023-04-01 01:26:16 +08:00
logger.debug(f"Host: {self.host}, Username: {self.username}, Password: {self.password}")
ex = ""
try:
self.client = Client(
host=self.host,
username=self.username,
password=self.password,
VERIFY_WEBUI_CERTIFICATE=False,
2023-06-24 22:06:03 +08:00
REQUESTS_ARGS={"timeout": (45, 60)},
)
self.client.auth_log_in()
2023-04-01 01:26:16 +08:00
self.current_version = self.client.app.version
logger.debug(f"qBittorrent: {self.current_version}")
logger.debug(f"qBittorrent Web API: {self.client.app.web_api_version}")
logger.debug(f"qbit_manage supported versions: {self.MIN_SUPPORTED_VERSION} - {self.SUPPORTED_VERSION}")
if self.current_version < self.MIN_SUPPORTED_VERSION:
ex = (
2023-04-01 01:26:16 +08:00
f"Qbittorrent Error: qbit_manage is only compatible with {self.MIN_SUPPORTED_VERSION} or higher. "
f"You are currently on {self.current_version}."
2022-10-29 23:19:09 +08:00
+ "\n"
+ f"Please upgrade your qBittorrent version to {self.MIN_SUPPORTED_VERSION} or higher to use qbit_manage."
2022-10-29 23:19:09 +08:00
)
2023-04-01 01:26:16 +08:00
elif not Version.is_app_version_supported(self.current_version):
ex = (
2023-04-01 01:26:16 +08:00
f"Qbittorrent Error: qbit_manage is only compatible with {self.SUPPORTED_VERSION} or lower. "
f"You are currently on {self.current_version}."
2022-10-29 23:19:09 +08:00
+ "\n"
+ f"Please downgrade your qBittorrent version to {self.SUPPORTED_VERSION} to use qbit_manage."
2022-10-29 23:19:09 +08:00
)
if ex:
if self.config.commands["skip_qb_version_check"]:
ex += "\n[BYPASS]: Continuing because qBittorrent version check is bypassed... Please do not ask for support!"
logger.print_line(ex, "WARN")
else:
self.config.notify(ex, "Qbittorrent")
logger.print_line(ex, "CRITICAL")
v4.0.5 (#418) * Fixes #388 * Bump docker/setup-buildx-action from 2 to 3 Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Bump docker/login-action from 2 to 3 Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Bump docker/build-push-action from 4 to 5 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4 to 5. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v4...v5) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Bump gitpython from 3.1.35 to 3.1.36 Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.35 to 3.1.36. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.35...3.1.36) --- updated-dependencies: - dependency-name: gitpython dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.11.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.11.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.11.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.11.0) - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) * Error handling when BHD API doesn't respond * add BHD specific announce related issues * handle JSONDecodeError * Special mapping to leave torrents uncategorized on cat-update (#398) Special mapping to leave torrents uncategorized on cat-update (closes #395) * Bump gitpython from 3.1.36 to 3.1.37 Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.36 to 3.1.37. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.36...3.1.37) --- updated-dependencies: - dependency-name: gitpython dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump ruamel-yaml from 0.17.32 to 0.17.33 Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.32 to 0.17.33. --- updated-dependencies: - dependency-name: ruamel-yaml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * last_active flag for share_limits (#397) Added a last_active flag for share_limits to resume torrents and avoid cleanup if there was activity in the last X minutes. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * [pre-commit.ci] pre-commit autoupdate (#405) updates: - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.11.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.11.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.13.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.13.0) - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * Bump schedule from 1.2.0 to 1.2.1 Bumps [schedule](https://github.com/dbader/schedule) from 1.2.0 to 1.2.1. - [Changelog](https://github.com/dbader/schedule/blob/master/HISTORY.rst) - [Commits](https://github.com/dbader/schedule/compare/1.2.0...1.2.1) --- updated-dependencies: - dependency-name: schedule dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump ruamel-yaml from 0.17.33 to 0.17.34 Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.33 to 0.17.34. --- updated-dependencies: - dependency-name: ruamel-yaml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * fix exit codes when program fails (#411) Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * Bump ruamel-yaml from 0.17.34 to 0.17.35 Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.34 to 0.17.35. --- updated-dependencies: - dependency-name: ruamel-yaml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * [pre-commit.ci] pre-commit autoupdate (#409) updates: - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.12.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.12.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.14.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.14.0) - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * New option cat in trackers (#400) * New option cat in trackers * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * update config.sample for #200 * add additional script to edit trackers * clarify remote_dir usage (#417) * Bump gitpython from 3.1.35 to 3.1.37 (#414) Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.35 to 3.1.37. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.35...3.1.37) --- updated-dependencies: - dependency-name: gitpython dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [pre-commit.ci] pre-commit autoupdate (#413) updates: - [github.com/pre-commit/pre-commit-hooks: v4.4.0 → v4.5.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.4.0...v4.5.0) - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.12.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.12.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.15.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.15.0) - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * 4.0.5 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Esteban Thilliez <77675611+estebanthi@users.noreply.github.com> Co-authored-by: Fabricio Silva <hi@fabricio.dev> Co-authored-by: bakerboy448 <55419169+bakerboy448@users.noreply.github.com>
2023-10-14 23:08:33 +08:00
sys.exit(1)
logger.info("Qbt Connection Successful")
except LoginFailed as exc:
ex = "Qbittorrent Error: Failed to login. Invalid username/password."
self.config.notify(ex, "Qbittorrent")
2023-07-16 03:03:29 +08:00
raise Failed(exc) from exc
except Exception as exc:
2023-07-16 03:03:29 +08:00
self.config.notify(exc, "Qbittorrent")
raise Failed(exc) from exc
logger.separator("Getting Torrent List", space=False, border=False)
2022-10-29 23:19:09 +08:00
self.torrent_list = self.get_torrents({"sort": "added_on"})
self.global_max_ratio_enabled = self.client.app.preferences.max_ratio_enabled
self.global_max_ratio = self.client.app.preferences.max_ratio
self.global_max_seeding_time_enabled = self.client.app.preferences.max_seeding_time_enabled
self.global_max_seeding_time = self.client.app.preferences.max_seeding_time
2023-04-10 23:52:51 +08:00
if any(config.commands.get(command, False) for command in self.TORRENT_DICT_COMMANDS):
2021-12-29 01:19:58 +08:00
# Get an updated torrent dictionary information of the torrents
2023-04-10 23:52:51 +08:00
self.get_torrent_info()
else:
self.torrentinfo = None
self.torrentissue = None
self.torrentvalid = None
2023-04-10 23:52:51 +08:00
def get_torrent_info(self):
"""
Will create a 2D Dictionary with the torrent name as the key
self.torrentinfo = {'TorrentName1' : {'Category':'TV', 'save_path':'/data/torrents/TV', 'count':1, 'msg':'[]'...},
'TorrentName2' : {'Category':'Movies', 'save_path':'/data/torrents/Movies'}, 'count':2, 'msg':'[]'...}
List of dictionary key definitions
Category = Returns category of the torrent (str)
save_path = Returns the save path of the torrent (str)
count = Returns a count of the total number of torrents with the same name (int)
msg = Returns a list of torrent messages by name (list of str)
status = Returns the list of status numbers of the torrent by name
(0: Tracker is disabled (used for DHT, PeX, and LSD),
1: Tracker has not been contacted yet,
2: Tracker has been contacted and is working,
3: Tracker is updating,
4: Tracker has been contacted, but it is not working (or doesn't send proper replies)
is_complete = Returns the state of torrent
(Returns True if at least one of the torrent with the State is categorized as Complete.)
first_hash = Returns the hash number of the original torrent (Assuming the torrent list is sorted by date added (Asc))
Takes in a number n, returns the square of n
"""
self.torrentinfo = {}
self.torrentissue = [] # list of unregistered torrent objects
self.torrentvalid = [] # list of working torrents
t_obj_list = [] # list of all torrent objects
settings = self.config.settings
logger.separator("Checking Settings", space=False, border=False)
if settings["force_auto_tmm"]:
logger.print_line(
"force_auto_tmm set to True. Will force Auto Torrent Management for all torrents.", self.config.loglevel
)
logger.separator("Gathering Torrent Information", space=True, border=True)
for torrent in self.torrent_list:
is_complete = False
msg = None
status = None
working_tracker = None
issue = {"potential": False}
if torrent.auto_tmm is False and settings["force_auto_tmm"] and torrent.category != "" and not self.config.dry_run:
torrent.set_auto_management(True)
try:
torrent_name = torrent.name
torrent_hash = torrent.hash
torrent_is_complete = torrent.state_enum.is_complete
save_path = torrent.save_path
category = torrent.category
torrent_trackers = torrent.trackers
except Exception as ex:
self.config.notify(ex, "Get Torrent Info", False)
logger.warning(ex)
if torrent_name in self.torrentinfo:
t_obj_list.append(torrent)
t_count = self.torrentinfo[torrent_name]["count"] + 1
msg_list = self.torrentinfo[torrent_name]["msg"]
status_list = self.torrentinfo[torrent_name]["status"]
is_complete = True if self.torrentinfo[torrent_name]["is_complete"] is True else torrent_is_complete
first_hash = self.torrentinfo[torrent_name]["first_hash"]
2022-08-14 04:49:02 +08:00
else:
2023-04-10 23:52:51 +08:00
t_obj_list = [torrent]
t_count = 1
msg_list = []
status_list = []
is_complete = torrent_is_complete
first_hash = torrent_hash
for trk in torrent_trackers:
if trk.url.startswith("http"):
status = trk.status
msg = trk.msg.upper()
if TrackerStatus(trk.status) == TrackerStatus.WORKING:
2023-04-10 23:52:51 +08:00
working_tracker = True
break
# Add any potential unregistered torrents to a list
if TrackerStatus(trk.status) == TrackerStatus.NOT_WORKING and not list_in_text(
2023-04-11 08:50:55 +08:00
msg, TorrentMessages.EXCEPTIONS_MSGS
):
2023-04-10 23:52:51 +08:00
issue["potential"] = True
issue["msg"] = msg
issue["status"] = status
if working_tracker:
status = 2
msg = ""
self.torrentvalid.append(torrent)
elif issue["potential"]:
status = issue["status"]
msg = issue["msg"]
self.torrentissue.append(torrent)
if msg is not None:
msg_list.append(msg)
if status is not None:
status_list.append(status)
torrentattr = {
"torrents": t_obj_list,
"Category": category,
"save_path": save_path,
"count": t_count,
"msg": msg_list,
"status": status_list,
"is_complete": is_complete,
"first_hash": first_hash,
2022-08-14 04:49:02 +08:00
}
2023-04-10 23:52:51 +08:00
self.torrentinfo[torrent_name] = torrentattr
2022-08-14 04:49:02 +08:00
2023-04-10 23:52:51 +08:00
def get_torrents(self, params):
"""Get torrents from qBittorrent"""
return self.client.torrents.info(**params)
2023-04-10 23:52:51 +08:00
def get_tags(self, trackers):
"""Get tags from config file based on keyword"""
urls = [x.url for x in trackers if x.url.startswith(("http", "udp", "ws"))]
2023-04-10 23:52:51 +08:00
tracker = {}
tracker["tag"] = None
v4.0.5 (#418) * Fixes #388 * Bump docker/setup-buildx-action from 2 to 3 Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Bump docker/login-action from 2 to 3 Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Bump docker/build-push-action from 4 to 5 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4 to 5. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v4...v5) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Bump gitpython from 3.1.35 to 3.1.36 Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.35 to 3.1.36. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.35...3.1.36) --- updated-dependencies: - dependency-name: gitpython dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.11.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.11.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.11.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.11.0) - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) * Error handling when BHD API doesn't respond * add BHD specific announce related issues * handle JSONDecodeError * Special mapping to leave torrents uncategorized on cat-update (#398) Special mapping to leave torrents uncategorized on cat-update (closes #395) * Bump gitpython from 3.1.36 to 3.1.37 Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.36 to 3.1.37. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.36...3.1.37) --- updated-dependencies: - dependency-name: gitpython dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump ruamel-yaml from 0.17.32 to 0.17.33 Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.32 to 0.17.33. --- updated-dependencies: - dependency-name: ruamel-yaml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * last_active flag for share_limits (#397) Added a last_active flag for share_limits to resume torrents and avoid cleanup if there was activity in the last X minutes. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * [pre-commit.ci] pre-commit autoupdate (#405) updates: - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.11.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.11.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.13.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.13.0) - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * Bump schedule from 1.2.0 to 1.2.1 Bumps [schedule](https://github.com/dbader/schedule) from 1.2.0 to 1.2.1. - [Changelog](https://github.com/dbader/schedule/blob/master/HISTORY.rst) - [Commits](https://github.com/dbader/schedule/compare/1.2.0...1.2.1) --- updated-dependencies: - dependency-name: schedule dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump ruamel-yaml from 0.17.33 to 0.17.34 Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.33 to 0.17.34. --- updated-dependencies: - dependency-name: ruamel-yaml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * fix exit codes when program fails (#411) Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * Bump ruamel-yaml from 0.17.34 to 0.17.35 Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.34 to 0.17.35. --- updated-dependencies: - dependency-name: ruamel-yaml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * [pre-commit.ci] pre-commit autoupdate (#409) updates: - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.12.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.12.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.14.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.14.0) - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * New option cat in trackers (#400) * New option cat in trackers * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * update config.sample for #200 * add additional script to edit trackers * clarify remote_dir usage (#417) * Bump gitpython from 3.1.35 to 3.1.37 (#414) Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.35 to 3.1.37. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.35...3.1.37) --- updated-dependencies: - dependency-name: gitpython dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [pre-commit.ci] pre-commit autoupdate (#413) updates: - [github.com/pre-commit/pre-commit-hooks: v4.4.0 → v4.5.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.4.0...v4.5.0) - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.12.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.12.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.15.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.15.0) - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * 4.0.5 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Esteban Thilliez <77675611+estebanthi@users.noreply.github.com> Co-authored-by: Fabricio Silva <hi@fabricio.dev> Co-authored-by: bakerboy448 <55419169+bakerboy448@users.noreply.github.com>
2023-10-14 23:08:33 +08:00
tracker["cat"] = None
2023-04-10 23:52:51 +08:00
tracker["notifiarr"] = None
tracker["url"] = None
tracker_other_tag = self.config.util.check_for_attribute(
self.config.data, "tag", parent="tracker", subparent="other", default_is_none=True, var_type="list", save=False
)
try:
tracker["url"] = util.trunc_val(urls[0], os.sep)
except IndexError as e:
tracker["url"] = None
if not urls:
urls = []
if not tracker_other_tag:
tracker_other_tag = ["other"]
tracker["url"] = "No http URL found"
else:
logger.debug(f"Tracker Url:{urls}")
logger.debug(e)
if "tracker" in self.config.data and self.config.data["tracker"] is not None:
tag_values = self.config.data["tracker"]
for tag_url, tag_details in tag_values.items():
for url in urls:
if tag_url in url:
if tracker["url"] is None:
default_tag = tracker_other_tag
else:
try:
tracker["url"] = util.trunc_val(url, os.sep)
default_tag = tracker["url"].split(os.sep)[2].split(":")[0]
except IndexError as e:
logger.debug(f"Tracker Url:{url}")
logger.debug(e)
2023-04-23 03:57:56 +08:00
tracker["tag"] = self.config.util.check_for_attribute(
self.config.data, "tag", parent="tracker", subparent=tag_url, default=tag_url, var_type="list"
)
v4.0.5 (#418) * Fixes #388 * Bump docker/setup-buildx-action from 2 to 3 Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Bump docker/login-action from 2 to 3 Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Bump docker/build-push-action from 4 to 5 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4 to 5. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v4...v5) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Bump gitpython from 3.1.35 to 3.1.36 Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.35 to 3.1.36. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.35...3.1.36) --- updated-dependencies: - dependency-name: gitpython dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.11.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.11.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.11.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.11.0) - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) * Error handling when BHD API doesn't respond * add BHD specific announce related issues * handle JSONDecodeError * Special mapping to leave torrents uncategorized on cat-update (#398) Special mapping to leave torrents uncategorized on cat-update (closes #395) * Bump gitpython from 3.1.36 to 3.1.37 Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.36 to 3.1.37. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.36...3.1.37) --- updated-dependencies: - dependency-name: gitpython dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump ruamel-yaml from 0.17.32 to 0.17.33 Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.32 to 0.17.33. --- updated-dependencies: - dependency-name: ruamel-yaml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * last_active flag for share_limits (#397) Added a last_active flag for share_limits to resume torrents and avoid cleanup if there was activity in the last X minutes. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * [pre-commit.ci] pre-commit autoupdate (#405) updates: - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.11.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.11.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.13.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.13.0) - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * Bump schedule from 1.2.0 to 1.2.1 Bumps [schedule](https://github.com/dbader/schedule) from 1.2.0 to 1.2.1. - [Changelog](https://github.com/dbader/schedule/blob/master/HISTORY.rst) - [Commits](https://github.com/dbader/schedule/compare/1.2.0...1.2.1) --- updated-dependencies: - dependency-name: schedule dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump ruamel-yaml from 0.17.33 to 0.17.34 Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.33 to 0.17.34. --- updated-dependencies: - dependency-name: ruamel-yaml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * fix exit codes when program fails (#411) Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * Bump ruamel-yaml from 0.17.34 to 0.17.35 Bumps [ruamel-yaml](https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree) from 0.17.34 to 0.17.35. --- updated-dependencies: - dependency-name: ruamel-yaml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * [pre-commit.ci] pre-commit autoupdate (#409) updates: - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.12.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.12.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.14.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.14.0) - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * New option cat in trackers (#400) * New option cat in trackers * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * update config.sample for #200 * add additional script to edit trackers * clarify remote_dir usage (#417) * Bump gitpython from 3.1.35 to 3.1.37 (#414) Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.35 to 3.1.37. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.35...3.1.37) --- updated-dependencies: - dependency-name: gitpython dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [pre-commit.ci] pre-commit autoupdate (#413) updates: - [github.com/pre-commit/pre-commit-hooks: v4.4.0 → v4.5.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.4.0...v4.5.0) - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.12.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.12.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.15.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.15.0) - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> * 4.0.5 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Esteban Thilliez <77675611+estebanthi@users.noreply.github.com> Co-authored-by: Fabricio Silva <hi@fabricio.dev> Co-authored-by: bakerboy448 <55419169+bakerboy448@users.noreply.github.com>
2023-10-14 23:08:33 +08:00
tracker["cat"] = self.config.util.check_for_attribute(
self.config.data,
"cat",
parent="tracker",
subparent=tag_url,
default_is_none=True,
var_type="str",
save=False,
do_print=False,
)
2023-04-23 03:57:56 +08:00
if tracker["tag"] == [tag_url]:
self.config.data["tracker"][tag_url]["tag"] = [tag_url]
if isinstance(tracker["tag"], str):
tracker["tag"] = [tracker["tag"]]
tracker["notifiarr"] = self.config.util.check_for_attribute(
self.config.data,
"notifiarr",
parent="tracker",
subparent=tag_url,
default_is_none=True,
do_print=False,
save=False,
)
2023-04-10 23:52:51 +08:00
return tracker
if tracker_other_tag:
tracker["tag"] = tracker_other_tag
tracker["notifiarr"] = self.config.util.check_for_attribute(
self.config.data,
"notifiarr",
parent="tracker",
subparent="other",
default_is_none=True,
do_print=False,
save=False,
)
return tracker
if tracker["url"]:
logger.trace(f"tracker url: {tracker['url']}")
if tracker_other_tag:
default_tag = tracker_other_tag
else:
default_tag = tracker["url"].split(os.sep)[2].split(":")[0]
tracker["tag"] = self.config.util.check_for_attribute(
self.config.data, "tag", parent="tracker", subparent=default_tag, default=default_tag, var_type="list"
)
if isinstance(tracker["tag"], str):
tracker["tag"] = [tracker["tag"]]
try:
self.config.data["tracker"][default_tag]["tag"] = [default_tag]
except Exception:
self.config.data["tracker"][default_tag] = {"tag": [default_tag]}
e = f'No tags matched for {tracker["url"]}. Please check your config.yml file. Setting tag to {default_tag}'
self.config.notify(e, "Tag", False)
logger.warning(e)
return tracker
def get_category(self, path):
"""Get category from config file based on path provided"""
category = ""
path = os.path.join(path, "")
if "cat" in self.config.data and self.config.data["cat"] is not None:
cat_path = self.config.data["cat"]
for cat, save_path in cat_path.items():
if os.path.join(save_path, "") == path:
category = cat
break
if not category:
default_cat = path.split(os.sep)[-2]
category = str(default_cat)
self.config.util.check_for_attribute(self.config.data, default_cat, parent="cat", default=path)
self.config.data["cat"][str(default_cat)] = path
e = f"No categories matched for the save path {path}. Check your config.yml file. - Setting category to {default_cat}"
self.config.notify(e, "Category", False)
logger.warning(e)
return category
def tor_delete_recycle(self, torrent, info):
"""Move torrent to recycle bin"""
2022-10-29 23:19:09 +08:00
if self.config.recyclebin["enabled"]:
tor_files = []
try:
info_hash = torrent.hash
save_path = torrent.save_path.replace(self.config.root_dir, self.config.remote_dir)
# Define torrent files/folders
for file in torrent.files:
tor_files.append(os.path.join(save_path, file.name))
except NotFound404Error:
return
2022-10-29 23:19:09 +08:00
if self.config.recyclebin["split_by_category"]:
recycle_path = os.path.join(save_path, os.path.basename(self.config.recycle_dir.rstrip(os.sep)))
else:
recycle_path = self.config.recycle_dir
2021-12-29 01:19:58 +08:00
# Create recycle bin if not exists
torrent_path = os.path.join(recycle_path, "torrents")
torrents_json_path = os.path.join(recycle_path, "torrents_json")
2023-06-04 19:44:17 +08:00
torrent_name = info["torrents"][0]
os.makedirs(recycle_path, exist_ok=True)
2022-10-29 23:19:09 +08:00
if self.config.recyclebin["save_torrents"]:
if os.path.isdir(torrent_path) is False:
os.makedirs(torrent_path)
if os.path.isdir(torrents_json_path) is False:
os.makedirs(torrents_json_path)
2023-06-04 19:44:17 +08:00
torrent_json_file = os.path.join(torrents_json_path, f"{torrent_name}.json")
torrent_json = util.load_json(torrent_json_file)
if not torrent_json:
2023-04-01 01:26:16 +08:00
logger.info(f"Saving Torrent JSON file to {torrent_json_file}")
2023-06-04 19:44:17 +08:00
torrent_json["torrent_name"] = torrent_name
torrent_json["category"] = info["torrent_category"]
2022-01-01 23:59:15 +08:00
else:
2023-04-01 01:26:16 +08:00
logger.info(f"Adding {info['torrent_tracker']} to existing {os.path.basename(torrent_json_file)}")
dot_torrent_files = []
for file in os.listdir(self.config.torrents_dir):
if file.startswith(info_hash):
dot_torrent_files.append(file)
try:
util.copy_files(os.path.join(self.config.torrents_dir, file), os.path.join(torrent_path, file))
except Exception as ex:
logger.stacktrace()
self.config.notify(ex, "Deleting Torrent", False)
2023-04-01 01:35:38 +08:00
logger.warning(f"RecycleBin Warning: {ex}")
if "tracker_torrent_files" in torrent_json:
tracker_torrent_files = torrent_json["tracker_torrent_files"]
else:
tracker_torrent_files = {}
tracker_torrent_files[info["torrent_tracker"]] = dot_torrent_files
2022-01-01 23:59:15 +08:00
if dot_torrent_files:
backup_str = "Backing up "
2022-01-01 23:59:15 +08:00
for idx, val in enumerate(dot_torrent_files):
2022-10-29 23:19:09 +08:00
if idx == 0:
backup_str += val
else:
backup_str += f" and {val.replace(info_hash,'')}"
2022-01-01 23:59:15 +08:00
backup_str += f" to {torrent_path}"
logger.info(backup_str)
torrent_json["tracker_torrent_files"] = tracker_torrent_files
if "files" not in torrent_json:
files_cleaned = [f.replace(self.config.remote_dir, "") for f in tor_files]
torrent_json["files"] = files_cleaned
if "deleted_contents" not in torrent_json:
torrent_json["deleted_contents"] = info["torrents_deleted_and_contents"]
else:
2022-10-29 23:19:09 +08:00
if torrent_json["deleted_contents"] is False and info["torrents_deleted_and_contents"] is True:
torrent_json["deleted_contents"] = info["torrents_deleted_and_contents"]
2022-01-01 23:59:15 +08:00
logger.debug("")
2023-04-01 01:26:16 +08:00
logger.debug(f"JSON: {torrent_json}")
util.save_json(torrent_json, torrent_json_file)
2022-10-29 23:19:09 +08:00
if info["torrents_deleted_and_contents"] is True:
logger.separator(f"Moving {len(tor_files)} files to RecycleBin", space=False, border=False, loglevel="DEBUG")
if len(tor_files) == 1:
logger.print_line(tor_files[0], "DEBUG")
else:
logger.print_line("\n".join(tor_files), "DEBUG")
logger.debug(
2023-04-01 01:26:16 +08:00
f"Moved {len(tor_files)} files to {recycle_path.replace(self.config.remote_dir,self.config.root_dir)}"
2022-10-29 23:19:09 +08:00
)
# Move files from torrent contents to Recycle bin
for file in tor_files:
src = file
dest = os.path.join(recycle_path, file.replace(self.config.remote_dir, ""))
# Move files and change date modified
try:
to_delete = util.move_files(src, dest, True)
except FileNotFoundError:
ex = logger.print_line(f"RecycleBin Warning - FileNotFound: No such file or directory: {src} ", "WARNING")
self.config.notify(ex, "Deleting Torrent", False)
# Delete torrent and files
torrent.delete(delete_files=to_delete)
# Remove any empty directories
util.remove_empty_directories(save_path, "**/*")
else:
torrent.delete(delete_files=False)
else:
2022-10-29 23:19:09 +08:00
if info["torrents_deleted_and_contents"] is True:
torrent.delete(delete_files=True)
else:
torrent.delete(delete_files=False)
2023-04-10 03:37:23 +08:00
try:
if torrent in self.torrent_list:
self.torrent_list.remove(torrent)
except ValueError:
logger.debug(f"Torrent {torrent.name} has already been deleted from torrent list.")