mirror of
https://github.com/StuffAnThings/qbit_manage.git
synced 2025-09-10 07:06:33 +08:00
BHD Integration for unregistered torrents #70
This commit is contained in:
parent
b42ef3328c
commit
2d0b7b675b
4 changed files with 102 additions and 44 deletions
|
@ -8,7 +8,7 @@ qbt:
|
|||
pass: "password"
|
||||
|
||||
settings:
|
||||
force_auto_tmm: False #Will force qBittorrent to enable Automatic Torrent Managment for each torrent.
|
||||
force_auto_tmm: False # Will force qBittorrent to enable Automatic Torrent Management for each torrent.
|
||||
|
||||
directory:
|
||||
# Do not remove these
|
||||
|
@ -173,3 +173,7 @@ webhooks:
|
|||
rem_orphaned: notifiarr
|
||||
tag_nohardlinks: notifiarr
|
||||
empty_recyclebin: notifiarr
|
||||
|
||||
#BHD Integration used for checking unregistered torrents
|
||||
bhd:
|
||||
apikey:
|
34
modules/bhd.py
Normal file
34
modules/bhd.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
import logging
|
||||
|
||||
from modules.util import Failed
|
||||
from json import JSONDecodeError
|
||||
|
||||
logger = logging.getLogger("qBit Manage")
|
||||
|
||||
base_url = "https://beyond-hd.me/api/"
|
||||
|
||||
class BeyondHD:
|
||||
def __init__(self, config, params):
|
||||
self.config = config
|
||||
self.apikey = params["apikey"]
|
||||
json = {"search":"test"}
|
||||
results = self.search(json)
|
||||
|
||||
def search(self, json, path="torrents/"):
|
||||
url = f"{base_url}{path}{self.apikey}"
|
||||
json["action"] = "search"
|
||||
if self.config.trace_mode:
|
||||
logger.debug(url.replace(self.apikey, "APIKEY"))
|
||||
logger.debug(f"JSON: {json}")
|
||||
try:
|
||||
response = self.config.post(url, json=json)
|
||||
response_json = response.json()
|
||||
except JSONDecodeError as e:
|
||||
if response.status_code >= 400:
|
||||
raise Failed(e)
|
||||
if response.status_code >= 400:
|
||||
logger.debug(f"Response: {response_json}")
|
||||
raise Failed(f"({response.status_code} [{response.reason}]) {response_json}")
|
||||
if not response_json["success"]:
|
||||
raise Failed(f"BHD Error: {response_json['status_message']}")
|
||||
return response.json()
|
|
@ -4,6 +4,7 @@ from modules.util import Failed, check
|
|||
from modules.qbittorrent import Qbt
|
||||
from modules.webhooks import Webhooks
|
||||
from modules.notifiarr import Notifiarr
|
||||
from modules.bhd import BeyondHD
|
||||
from modules.apprise import Apprise
|
||||
from ruamel import yaml
|
||||
from retrying import retry
|
||||
|
@ -67,6 +68,7 @@ class Config:
|
|||
hooks("tag_nohardlinks")
|
||||
hooks("empty_recyclebin")
|
||||
new_config["webhooks"] = temp
|
||||
if "bhd" in new_config: new_config["bhd"] = new_config.pop("bhd")
|
||||
yaml.round_trip_dump(new_config, open(self.config_path, "w", encoding="utf-8"), indent=None, block_seq_indent=2)
|
||||
self.data = new_config
|
||||
except yaml.scanner.ScannerError as e:
|
||||
|
@ -125,6 +127,20 @@ class Config:
|
|||
util.print_stacktrace()
|
||||
logger.error(f"Webhooks Error: {e}")
|
||||
|
||||
self.BeyondHD = None
|
||||
if "bhd" in self.data:
|
||||
if self.data["bhd"] is not None:
|
||||
logger.info("Connecting to BHD API...")
|
||||
try:
|
||||
self.BeyondHD = BeyondHD(self, {
|
||||
"apikey": self.util.check_for_attribute(self.data, "apikey", parent="bhd", throw=True)
|
||||
})
|
||||
except Failed as e:
|
||||
logger.error(e)
|
||||
self.notify(e,'BHD')
|
||||
logger.info(f"BHD Connection {'Failed' if self.BeyondHD is None else 'Successful'}")
|
||||
|
||||
|
||||
#nohardlinks
|
||||
self.nohardlinks = None
|
||||
if "nohardlinks" in self.data and self.args['tag_nohardlinks']:
|
||||
|
|
|
@ -86,7 +86,7 @@ class Qbt:
|
|||
if x.url.startswith('http'):
|
||||
status = x.status
|
||||
msg = x.msg.upper()
|
||||
exception = ["DOWN","UNREACHABLE","BAD GATEWAY"]
|
||||
exception = ["DOWN","UNREACHABLE","BAD GATEWAY","TRACKER UNAVAILABLE"]
|
||||
#Add any potential unregistered torrents to a list
|
||||
if x.status == 4 and all(x not in msg for x in exception):
|
||||
t_obj_unreg.append(torrent)
|
||||
|
@ -349,25 +349,54 @@ class Qbt:
|
|||
del_tor_cont = 0
|
||||
pot_unreg = 0
|
||||
pot_unr_summary = ''
|
||||
|
||||
def del_unregistered():
|
||||
nonlocal dry_run,loglevel,del_tor,del_tor_cont,t_name,msg_up,tracker,t_cat,t_msg,t_status,torrent
|
||||
body = []
|
||||
body += print_line(util.insert_space(f'Torrent Name: {t_name}',3),loglevel)
|
||||
body += print_line(util.insert_space(f'Status: {msg_up}',9),loglevel)
|
||||
body += print_line(util.insert_space(f'Tracker: {tracker["url"]}',8),loglevel)
|
||||
attr = {
|
||||
"function":"rem_unregistered",
|
||||
"title":"Removing Unregistered Torrents",
|
||||
"torrent_name":t_name,
|
||||
"torrent_category":t_cat,
|
||||
"torrent_status": msg_up,
|
||||
"torrent_tracker": tracker["url"],
|
||||
"notifiarr_indexer": tracker["notifiarr"],
|
||||
}
|
||||
if t_count > 1:
|
||||
# Checks if any of the original torrents are working
|
||||
if '' in t_msg or 2 in t_status:
|
||||
if not dry_run: torrent.delete(hash=torrent.hash, delete_files=False)
|
||||
attr["torrents_deleted_and_contents"] = False
|
||||
body += print_line(util.insert_space(f'Deleted .torrent but NOT content files.',8),loglevel)
|
||||
del_tor += 1
|
||||
else:
|
||||
if not dry_run: self.tor_delete_recycle(torrent)
|
||||
attr["torrents_deleted_and_contents"] = True
|
||||
body += print_line(util.insert_space(f'Deleted .torrent AND content files.',8),loglevel)
|
||||
del_tor_cont += 1
|
||||
else:
|
||||
if not dry_run: self.tor_delete_recycle(torrent)
|
||||
attr["torrents_deleted_and_contents"] = True
|
||||
body += print_line(util.insert_space(f'Deleted .torrent AND content files.',8),loglevel)
|
||||
del_tor_cont += 1
|
||||
attr["body"] = "\n".join(body)
|
||||
self.config.send_notifications(attr)
|
||||
|
||||
if self.config.args['rem_unregistered']:
|
||||
separator(f"Removing Unregistered Torrents", space=False, border=False)
|
||||
unreg_msgs = [
|
||||
'UNREGISTERED',
|
||||
'TORRENT NOT FOUND',
|
||||
'TORRENT IS NOT FOUND',
|
||||
'NOT REGISTERED',
|
||||
'HTTPS://BEYOND-HD.ME/TORRENTS',
|
||||
'NOT REGISTERED',
|
||||
'NOT EXIST',
|
||||
'UNKNOWN TORRENT',
|
||||
'REDOWNLOAD',
|
||||
'PACKS',
|
||||
'REPACKED',
|
||||
'PACK',
|
||||
'TRUMP',
|
||||
'RETITLED',
|
||||
'PRE-RETAIL',
|
||||
'FULL SEASON',
|
||||
'MASS REMOVAL'
|
||||
'TRUNCATED'
|
||||
]
|
||||
for torrent in self.torrentvalid:
|
||||
check_tags = util.get_list(torrent.tags)
|
||||
|
@ -387,6 +416,13 @@ class Qbt:
|
|||
msg_up = x.msg.upper()
|
||||
#Tag any potential unregistered torrents
|
||||
if not any(m in msg_up for m in unreg_msgs) and x.status == 4 and 'issue' not in check_tags:
|
||||
#Check for unregistered torrents using BHD API if the tracker is BHD
|
||||
if 'tracker.beyond-hd.me' in torrent.tracker and self.config.BeyondHD is not None:
|
||||
json = {"info_hash": torrent_hash}
|
||||
response = self.config.BeyondHD.search(json)
|
||||
if response['total_results'] <= 1:
|
||||
del_unregistered()
|
||||
break
|
||||
pot_unr = ''
|
||||
pot_unr += (util.insert_space(f'Torrent Name: {t_name}',3)+'\n')
|
||||
pot_unr += (util.insert_space(f'Status: {msg_up}',9)+'\n')
|
||||
|
@ -408,44 +444,12 @@ class Qbt:
|
|||
self.config.send_notifications(attr)
|
||||
if not dry_run: torrent.add_tags(tags='issue')
|
||||
if any(m in msg_up for m in unreg_msgs) and x.status == 4:
|
||||
body = []
|
||||
body += print_line(util.insert_space(f'Torrent Name: {t_name}',3),loglevel)
|
||||
body += print_line(util.insert_space(f'Status: {msg_up}',9),loglevel)
|
||||
body += print_line(util.insert_space(f'Tracker: {tracker["url"]}',8),loglevel)
|
||||
attr = {
|
||||
"function":"rem_unregistered",
|
||||
"title":"Removing Unregistered Torrents",
|
||||
"torrent_name":t_name,
|
||||
"torrent_category":t_cat,
|
||||
"torrent_status": msg_up,
|
||||
"torrent_tracker": tracker["url"],
|
||||
"notifiarr_indexer": tracker["notifiarr"],
|
||||
}
|
||||
if t_count > 1:
|
||||
# Checks if any of the original torrents are working
|
||||
if '' in t_msg or 2 in t_status:
|
||||
if not dry_run: torrent.delete(hash=torrent.hash, delete_files=False)
|
||||
attr["torrents_deleted_and_contents"] = False
|
||||
body += print_line(util.insert_space(f'Deleted .torrent but NOT content files.',8),loglevel)
|
||||
del_tor += 1
|
||||
else:
|
||||
if not dry_run: self.tor_delete_recycle(torrent)
|
||||
attr["torrents_deleted_and_contents"] = True
|
||||
body += print_line(util.insert_space(f'Deleted .torrent AND content files.',8),loglevel)
|
||||
del_tor_cont += 1
|
||||
else:
|
||||
if not dry_run: self.tor_delete_recycle(torrent)
|
||||
attr["torrents_deleted_and_contents"] = True
|
||||
body += print_line(util.insert_space(f'Deleted .torrent AND content files.',8),loglevel)
|
||||
del_tor_cont += 1
|
||||
attr["body"] = "\n".join(body)
|
||||
self.config.send_notifications(attr)
|
||||
del_unregistered()
|
||||
if del_tor >=1 or del_tor_cont >=1:
|
||||
if del_tor >= 1: print_line(f"{'Did not delete' if dry_run else 'Deleted'} {del_tor} .torrent{'s' if del_tor > 1 else ''} but not content files.",loglevel)
|
||||
if del_tor_cont >= 1: print_line(f"{'Did not delete' if dry_run else 'Deleted'} {del_tor_cont} .torrent{'s' if del_tor_cont > 1 else ''} AND content files.",loglevel)
|
||||
else:
|
||||
print_line('No unregistered torrents found.',loglevel)
|
||||
|
||||
if (pot_unreg > 0):
|
||||
separator(f"{pot_unreg} Potential Unregistered torrents found", space=False, border=False,loglevel=loglevel)
|
||||
print_multiline(pot_unr_summary.rstrip(),loglevel)
|
||||
|
|
Loading…
Add table
Reference in a new issue